Esempio n. 1
0
 def parse(cls, packet):
     """
         Parse DNS packet data and return DNSRecord instance
         Recursively parses sections (calling appropriate parse method)
     """
     buffer = DNSBufferExt(packet)
     try:
         header = DNSHeader.parse(buffer)
         questions = []
         rr = []
         auth = []
         ar = []
         for i in range(header.q):
             questions.append(DNSQuestion.parse(buffer))
         for i in range(header.a):
             rr.append(RR.parse(buffer))
         for i in range(header.auth):
             auth.append(RR.parse(buffer))
         for i in range(header.ar):
             ar.append(RR.parse(buffer))
         return cls(header, questions, rr, auth=auth, ar=ar)
     except DNSError:
         raise
     except (BufferError, BimapError) as e:
         raise DNSError(f"Error unpacking DNSRecord [offset={buffer.offset:d}]: {e}")
Esempio n. 2
0
    def transmit(self, payload):

        """
        This is the original transmit method from ServerTarget overwritten with
        DNS response code specific reporting

        Accordin to:
        https://support.umbrella.com/hc/en-us/articles/232254248-Common-DNS-return-codes-for-any-DNS-service-and-Umbrella-

        NOERROR     RCODE:0     DNS Query completed successfully
        FORMERR     RCODE:1     DNS Query Format Error
        SERVFAIL    RCODE:2     Server failed to complete the DNS request
        NXDOMAIN    RCODE:3     Domain name does not exist.
        NOTIMP      RCODE:4     Function not implemented
        REFUSED     RCODE:5     The server refused to answer for the query
        YXDOMAIN    RCODE:6     Name that should not exist, does exist
        XRRSET      RCODE:7     RRset that should not exist, does exist
        NOTAUTH     RCODE:8     Server not authoritative for the zone
        NOTZONE     RCODE:9     Name not in zone

        Original method docstring:
        Transmit single payload, and receive response, if expected.
        The actual implementation of the send/receive should be in
        ``_send_to_target`` and ``_receive_from_target``.

        :type payload: str
        :param payload: payload to send
        :rtype: str
        :return: the response (if received)
        """

        DNS_RETRUN_CODES = [
            'NOERROR',
            'FORMERR',
            'SERVFAIL',
            'NXDOMAIN',
            'NOTIMP',
            'REFUSED',
            'YXDOMAIN',
            'XRRSET',
            'NOTAUTH',
            'NOTZONE'
        ]

        DNS_EXCLUDE = [0, 3, 5]

        response = None
        trans_report_name = 'transmission_0x%04x' % self.transmission_count
        trans_report = Report(trans_report_name)
        self.transmission_report = trans_report
        self.report.add(trans_report_name, trans_report)
        try:
            trans_report.add('request (hex)', hexlify(payload).decode())
            trans_report.add('request (raw)', '%s' % payload)
            trans_report.add('request length', len(payload))
            trans_report.add('request time', time.time())

            request = hexlify(payload).decode()
            request = request if len(request) < 100 else (request[:100] + ' ...')
            self.logger.info(f"request({len(payload)}): {request}")

            self._send_to_target(payload)

            trans_report.success()

            if self.expect_response:
                try:
                    response = self._receive_from_target()
                    trans_report.add('response time', time.time())
                    trans_report.add('response (hex)', hexlify(response).decode())
                    trans_report.add('response (raw)', '%s' % response)
                    trans_report.add('response length', len(response))
                    trans_report.add('Session ID', str(self._uuid))
                    printed_response = hexlify(response).decode()
                    printed_response = printed_response if len(printed_response) < 100 else (printed_response[:100]
                                                                                             + ' ...')
                    self.logger.info(f"response({len(response)}): {printed_response}")

                    server_message = response.split(b',', 0)
                    reply = codecs.encode(server_message[0], 'hex')

                    # USE DNS LIB TO HELP DEBUGGING MALFORMED HEADER
                    debug_response_header = DNSBufferExt(unhexlify(reply))
                    parsed_dns_response_header = DNSHeader.parse(debug_response_header)
                    dns_response_message = DNSRecordExt.parse(server_message[0])

                    if int(parsed_dns_response_header.rcode) not in DNS_EXCLUDE:
                        self.logger.error(f"DNS response code: "
                                          f"{DNS_RETRUN_CODES[int(parsed_dns_response_header.rcode)]}")
                        self.logger.error(f"Debug header: {str(parsed_dns_response_header)}")
                        trans_report.failed(f"Failure in response, code: "
                                            f"{DNS_RETRUN_CODES[int(parsed_dns_response_header.rcode)]}")
                        trans_report.add('Response', str(dns_response_message))
                        trans_report.add('traceback', traceback.format_exc())
                        self.receive_failure = True
                        self.report.set_status('failed')

                except Exception as ex2:
                    trans_report.failed('failed to receive response: %s' % ex2)
                    trans_report.add('traceback', traceback.format_exc())
                    self.logger.error(f"target.transmit - failure in receive (exception: {ex2})")
                    self.logger.error(traceback.format_exc())
                    self.receive_failure = True
            else:
                response = ''
        except Exception as ex1:
            trans_report.failed('failed to send payload: %s' % ex1)
            trans_report.add('traceback', traceback.format_exc())
            self.logger.error(f"target.transmit - failure in send (exception: {ex1})")
            self.logger.error(traceback.format_exc())
            self.send_failure = True
        self.transmission_count += 1
        return response