abril 15, 2006

Servidor Fake DNS en python

La idea es tener un servidor dns del que podamos controlar sus respuestas y así poder asociar dominios con la ip que nosotros queramos, una de sus aplicaciones es el análisis de malware. Todo esto proviene de una necesidad que en su momento vi satisfecha con el Malcode Analyst Pack:
  fakeDNS - spoofs dns responses to controlled ip's

Lo único malo es que se trata de una utilidad para windows, así que como estos días he tenido un ratito, he aquí un script en python que corre en cualquier plataforma que soporte este mismo lenguaje.

Su funcionalidad es completamente básica, responde a cualquier query con un registro A (address) que apunta a la IP que nosotros hayamos designado. Tiene por defecto configurado un ttl bastante bajo (1 minuto, de cara al cacheo) y por su función es necesario privilegios administrativos para arrancarlo.

import socket

class DNSQuery:
def __init__(self, data):
self.data=data
self.dominio=''

tipo = (ord(data[2]) >> 3) & 15 # 4bits de tipo de consulta
if tipo == 0: # Standard query
ini=12
lon=ord(data[ini])
while lon != 0:
self.dominio+=data[ini+1:ini+lon+1]+'.'
ini+=lon+1
lon=ord(data[ini])

def respuesta(self, ip):
packet=''
if self.dominio:
packet+=self.data[:2] + "\x81\x80"
packet+=self.data[4:6] + self.data[4:6] + '\x00\x00\x00\x00' # Numero preg y respuestas
packet+=self.data[12:] # Nombre de dominio original
packet+='\xc0\x0c' # Puntero al nombre de dominio
packet+='\x00\x01\x00\x01\x00\x00\x00\x3c\x00\x04' # Tipo respuesta, ttl, etc
packet+=str.join('',map(lambda x: chr(int(x)), ip.split('.'))) # La ip en hex
return packet

if __name__ == '__main__':
ip='192.168.1.1'
print 'pyminifakeDNS:: dom.query. 60 IN A %s' % ip

udps = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udps.bind(('',53))

try:
while 1:
data, addr = udps.recvfrom(1024)
p=DNSQuery(data)
udps.sendto(p.respuesta(ip), addr)
print 'Respuesta: %s -> %s' % (p.dominio, ip)
except KeyboardInterrupt:
print 'Finalizando'
udps.close()


Para comprender el script y el por qué de los valores hexadecimales, tanto de los que se consultan como de los que se envían, es necesario echar un vistazo al rfc de las especificaciones de dns:
4.1.1. Header section format

The header contains the following fields:

1 1 1 1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ID |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR| Opcode |AA|TC|RD|RA| Z | RCODE |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| QDCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ANCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| NSCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ARCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+


Aunque para ver comodamente los paquetes, el ethereal:






Tags:

comentarios:

Anónimo dijo...

Excelente articulo!! :D,
simple, sencillo, util.

Enorabuena