Question

I'm working on adapting this small piece of Python code to my own use (it's from the sendpkm DNS spoofing tool, used to redirect the original Pokémon DS games' DNS requests to ones own computer.)

def dnsspoof():
  s=socket.socket(); s.connect(("bash.org",80));
  me="".join(chr(int(x)) for x in s.getsockname()[0].split("."))
  print "Please set your DS's DNS server to",s.getsockname()[0]
  dnsserv=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  dnsserv.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
  dnsserv.bind(("0.0.0.0",53))
  while True:
    r=dnsserv.recvfrom(512)
    s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.connect(('4.2.2.2', 53))
s.send(r[0])
rr=s.recv(512)
if "gamestats2" in rr: rr=rr[:-4]+me
dnsserv.sendto(rr, r[1])

serv=None
log=None

Would someone be so kind as to walk me through the sockets and explain how this is returning an IP for a DNS query? I'm just learning about Python.

Was it helpful?

Solution

Port 53 is the standard DNS port. But this code doesn't know anything about DNS beyond that number. All it does is listen on port 53, forward any requests to a server at 4.2.2.2, and return whatever that server returns.

In other words, it's a dumb byte proxy on port 53, which works because the remote server is a DNS server.

If you want to know how it works:

dnsserv=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
dnsserv.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
dnsserv.bind(("0.0.0.0",53))

This is standard code to create a socket to listen on a port. You're listening for UDP because that's what INET/DGRAM means. The setsockopt means that if you quit and restart the server it will be able to grab the same port again. And the bind says to listen on all IPv4 addresses on port 53.

The loop reads packets of up to 512 bytes, connects to the remote server and sends the same packets, reads the response from the server, and sends it back to the client. Because recvfrom returns a tuple of (data, address), you send r[0] to the server, and send the response to r[1]. (This part would be a lot more readable with tuple unpacking: data, address = recvfrom(...). Then you could use names instead of r[0].)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top