So today I’ve been playing with python and decided to make an arp ping utility. When i get more time i’ll turn this into a simple arp scanner.
I know that this is all possible using scapy but the idea of this was to teach myself how raw sockets work within python.
This requires netifaces and a few other modules that can usually be obtained using sudo easy_install modulename (you’ll require python-dev as well)
This script requires that you run as root in order to send and capture raw packets
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | #!/usr/bin/env python """ Author: phillips321 contact at phillips321.co.uk License: CC BY-SA 3.0 Use: Simple python arp ping Released: www.phillips321.co.uk Dependencies: netifaces (needs python-dev then easy_install netifaces) ChangeLog: v0.2 - fixed response to search for target ip v0.1 - first release """ version = "0.2" import socket import struct import sys import netifaces import binascii if len(sys.argv) == 3 : target = sys.argv[1] interface = sys.argv[2] elif len(sys.argv) == 2: target = sys.argv[1] interface = "eth0" print "No interface given so defaulting to eth0" else: #no values defined print help print "Usage: %s IP [interface] \n eg: %s 192.168.1.0 eth0" % (sys.argv[0],sys.argv[0]) exit(1) networkdetails = netifaces.ifaddresses(interface) ipaddress = networkdetails[2][0]['addr'] macaddress = networkdetails[17][0]['addr'] print "Attempting to arp ping %s from %s using %s" % (target,ipaddress,macaddress) # create packet eth_hdr = struct.pack("!6s6s2s", '\xff\xff\xff\xff\xff\xff', macaddress.replace(':','').decode('hex'), '\x08\x06') arp_hdr = struct.pack("!2s2s1s1s2s", '\x00\x01', '\x08\x00', '\x06', '\x04', '\x00\x01') arp_sender = struct.pack("!6s4s", macaddress.replace(':','').decode('hex'), socket.inet_aton(ipaddress)) arp_target = struct.pack("!6s4s", '\x00\x00\x00\x00\x00\x00', socket.inet_aton(target)) count = 5 while count != 0: count = count - 1 try: # send packet rawSocket = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.htons(0x0806)) rawSocket.bind((interface, socket.htons(0x0806))) rawSocket.send(eth_hdr + arp_hdr + arp_sender + arp_target) # wait for response rawSocket = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.htons(0x0806)) rawSocket.settimeout(0.5) response = rawSocket.recvfrom(2048) if target == socket.inet_ntoa(response[0][28:32]): print "Response from the folloiwing mac " + binascii.hexlify(response[0][6:12]).swapcase() break continue except socket.timeout: print "Attempt number %i did not get a response" % (count + 1) continue |
Or using scapy:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
"""
Author: phillips321 contact at phillips321.co.uk
License: CC BY-SA 3.0
Use: Simple scapy arpscanner
Released: www.phillips321.co.uk
Dependencies:
scapy
ChangeLog:
v0.2 - first release
"""
version = "0.2"
import sys, netifaces, thread
from scapy.all import *
if len(sys.argv) == 2 :
interface = sys.argv[1]
else: #no values defined print help
print "Usage: %s [interface] \n eg: %s eth0" % (sys.argv[0],sys.argv[0])
exit(1)
sourceipaddress = netifaces.ifaddresses(interface)[2][0]['addr']
netmask = netifaces.ifaddresses(interface)[2][0]['netmask']
starttime = time.time()
answered,unanswered=srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst="192.168.0.0/24"), timeout=2, verbose=0)
endtime = time.time()
totaltime = endtime - starttime
print "Sent ARP requests in %f seconds..." % (totaltime)
for i in range(0,len(answered)):
print "Response from " + answered[i][1].psrc + " using " + answered[i][1].hwsrc
completedtime = time.time()
totaltime = completedtime - starttime
print "Completed scan in %f seconds..." % (totaltime)
http://pastie.org/4337518
meh, i had time after training to write a quick arpscanner using python:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
"""
Author: phillips321 contact at phillips321.co.uk
License: CC BY-SA 3.0
Use: Simple python arpscanner
Released: www.phillips321.co.uk
Dependencies:
netifaces (needs python-dev then easy_install netifaces)
ChangeLog:
v0.1 - first release
"""
version = "0.1"
import socket, struct, sys, netifaces, binascii, thread, time
if len(sys.argv) == 2 :
interface = sys.argv[1]
else: #no values defined print help
print "Usage: %s [interface] \n eg: %s eth0" % (sys.argv[0],sys.argv[0])
exit(1)
networkdetails = netifaces.ifaddresses(interface)
sourceipaddress = networkdetails[2][0]['addr']
sourcemacaddress = networkdetails[17][0]['addr']
def worker_thread(target, sourceipaddress, sourcemacaddress):
# create packet
eth_hdr = struct.pack("!6s6s2s", '\xff\xff\xff\xff\xff\xff', sourcemacaddress.replace(':','').decode('hex'), '\x08\x06')
arp_hdr = struct.pack("!2s2s1s1s2s", '\x00\x01', '\x08\x00', '\x06', '\x04', '\x00\x01')
arp_sender = struct.pack("!6s4s", sourcemacaddress.replace(':','').decode('hex'), socket.inet_aton(sourceipaddress))
arp_target = struct.pack("!6s4s", '\x00\x00\x00\x00\x00\x00', socket.inet_aton(target))
try:
# send packet
rawSocket = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.htons(0x0806))
rawSocket.bind((interface, socket.htons(0x0806)))
rawSocket.send(eth_hdr + arp_hdr + arp_sender + arp_target)
# wait for response
rawSocket = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.htons(0x0806))
rawSocket.settimeout(0.5)
response = rawSocket.recvfrom(2048)
responseMACraw = binascii.hexlify(response[0][6:12])
responseMAC = ":".join(responseMACraw[x:x+2] for x in xrange(0, len(responseMACraw), 2))
responseIP = socket.inet_ntoa(response[0][28:32])
if target == responseIP:
print "Response from the mac %s on IP %s" % (responseMAC, responseIP)
except socket.timeout:
time.sleep(1)
for i in range(256):
target = "192.168.0." + str(i)
thread.start_new_thread(worker_thread, (target, sourceipaddress, sourcemacaddress))
time.sleep(0.2)
download from here: http://pastie.org/4326656