Skip to content

Instantly share code, notes, and snippets.

@NaPs
Created September 20, 2008 12:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save NaPs/11750 to your computer and use it in GitHub Desktop.
Save NaPs/11750 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
# Written by Antoine 'NaPs' Millet
#
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
# Version 2, December 2004
#
# Copyright (C) 2004 Sam Hocevar
# 14 rue de Plaisance, 75014 Paris, France
# Everyone is permitted to copy and distribute verbatim or modified
# copies of this license document, and changing it is allowed as long
# as the name is changed.
#
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
#
# 0. You just DO WHAT THE FUCK YOU WANT TO.
#
import struct
from socket import *
# Configuration :
protocol = 0x0806 # ARP Protocol
if_name = 'eth0' # Network interface to bind to socket
# End of configuration
# Funcs :
def mac2string(macaddr):
return ':'.join(['%02X' % (ord(c)) for c in macaddr])
def ip2string(ipaddr):
return '.'.join([str(ord(c)) for c in ipaddr])
def val2int(val):
return int(''.join(['%02d'%ord(c) for c in val]), 16)
# End of funcs
if __name__ == '__main__':
s = socket(AF_PACKET, SOCK_RAW, SOCK_RAW) # This is a raw socket,
# script must be executed
# as root !
s.bind((if_name, SOCK_RAW))
#mac_addr = s.getsockname()[4] # getting mac address
while True: # Main while
frame = s.recv(1048) # Getting last frame in netbuff
# Ethernet frame :
# +------------+------------+----+----------+
# | 6B | 6B | 2B | ...1498B |
# +------------+------------+----+----------+
# | @ dest | @ src |type| data... |
# +------------+------------+----+----------+
#
# So, frame[:14] are ethernet headers, and frame[14:] are data
# ARP packet :
# +----+----+--+--+----+------------------+
# | 2B | 2B |1B|1B| 2B | dep of *1*2 |
# +----+----+--+--+----+------------------+
# |HWty|PTty|*1|*2| op | Addrs |
# +----+----+--+--+----+------------------+
# *1 : Hardware address length
# *2 : Protocol address length
#
# So, frame[14:22] are arp headers, and frame[22:x] addresses,
# x depending of hw and proto addresses sizes.
# Decoding :
# Getting "type" field in ethernet headers
proto_type = val2int(struct.unpack('!2s', frame[12:14])[0])
# Filter frames which are not arp frames
if proto_type != protocol:
continue
arp_headers = frame[14:22]
arp_headers_values = struct.unpack('!2s2s1s1s2s', arp_headers)
hw_type, pt_type, hw_size, pt_size, operation = \
[val2int(v) for v in arp_headers_values]
total_addresses_byte = hw_size * 2 + pt_size * 2
arp_addrs = frame[22:22 + total_addresses_byte]
src_hw, src_pt, dst_hw, dst_pt = struct.unpack(
'!%ss%ss%ss%ss' % (hw_size, pt_size, hw_size, pt_size),
arp_addrs)
if operation == 1: # ARP Request
print '[%s / %s] Who is %s ?' % (
mac2string(src_hw),
ip2string(src_pt),
ip2string(dst_pt)
)
elif operation == 2: # ARP Reply
print '[%s / %s] I\'m %s' % (
mac2string(src_hw),
ip2string(src_pt),
ip2string(src_pt)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment