Ejemplo n.º 1
0
    def __init__(self):
        self.base = Base()
        self.sniff = Sniff_raw()
        self.dns = DNS_raw()

        self.rawSocket = socket(AF_PACKET, SOCK_RAW)

        self.port = 53
        self.A_DNS_QUERY = 1
        self.AAAA_DNS_QUERY = 28
Ejemplo n.º 2
0
class DnsResolver:
    """
    DNS resolver class
    """

    #  DNS packet:
    #
    #  0                 16                 31
    #  +------------------+------------------+
    #  |  Transaction ID  |      Flags       |
    #  +------------------+------------------+
    #  |    Questions     |    Answer RRS    |
    #  +------------------+------------------+
    #  |  Authority RRs   |  Additional RRs  |
    #  +------------------+------------------+
    #  |          Queries ...
    #  +---------------- ...

    # region Set variables

    # region Init Raw-packet classes
    base = Base()  # type: Base
    arp_scan = ArpScan()  # type: ArpScan
    dns = DNS_raw()  # type: DNS_raw
    # endregion

    # region Variables
    domain = ''  # type: str
    subdomains = list()  # type: List[str]
    available_characters = list([
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
        'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
        's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '-'
    ])  # type: List[str]
    results = list()  # type: List[Dict[str, str]]

    # endregion

    # endregion

    # region Init
    def __init__(
            self,
            network_interface,  # type: str
            quiet=False  # type: bool
    ):
        # type: (...) -> None
        """
        Init class DnsResolver
        :param network_interface: Network interface (example: eth0)
        :param quiet: Quiet mode on if True, quiet mode off if False (default: False)
        """

        # Set network interface for sending DNS queries
        self.network_interface = network_interface  # type: str

        # Set quiet mode
        self.quiet = quiet  # type: bool

        # Get MAC, IPv4 and IPv6 addresses for network interface
        self.your_mac_address = self.base.get_netiface_mac_address(
            self.network_interface)  # type: str
        self.your_ipv4_address = self.base.get_netiface_ip_address(
            self.network_interface)  # type: str
        self.your_ipv6_address = self.base.get_netiface_ipv6_link_address(
            self.network_interface, False)  # type: str

    # __init__.__annotations__ = {
    #     'network_interface': str,
    #     'quiet': bool,
    #     'return': None
    # }
    # endregion

    # region Parse DNS packet function
    def _parse_packet(
            self,
            response  # type: Dict[str, Dict[str, Union[str, Dict[str, str]]]]
    ):
        # type: (...) -> None
        """
        Parse DNS answers
        :param response: DNS answer dictionary
        :return: None
        """

        if 'DNS' in response.keys():

            if len(response['DNS']['answers']) > 0:

                for answer in response['DNS']['answers']:

                    if self.domain in answer['name']:

                        if answer['type'] == 1:
                            self.results.append({
                                'Domain':
                                answer['name'][:-1],
                                'IPv4 address':
                                answer['address'],
                                'IPv6 address':
                                '-'
                            })
                            self.base.print_success('Domain: ',
                                                    answer['name'][:-1],
                                                    ' IPv4: ',
                                                    answer['address'])

                        if answer['type'] == 28:
                            self.results.append({
                                'Domain':
                                answer['name'][:-1],
                                'IPv4 address':
                                '-',
                                'IPv6 address':
                                answer['address']
                            })

                            self.base.print_success('Domain: ',
                                                    answer['name'][:-1],
                                                    ' IPv6: ',
                                                    answer['address'])

    # _parse_packet.__annotations__ = {
    #     'request': Dict[str, Dict[str, Union[str, Dict[str, str]]]],
    #     'return': None
    # }
    # endregion

    # region Sniff DNS packets function
    def _sniff_packets(
            self,
            destination_mac_address,  # type: str
            destination_ipv4_address,  # type: str
            destination_ipv6_address,  # type: str
            source_port=53  # type: int
    ):
        # type: (...) -> None
        """
        Sniff DNS answers
        :param destination_mac_address: Destination MAC address in DNS answer (most likely this is MAC address on your network interface)
        :param destination_ipv4_address: Destination IPv4 address in DNS answer (most likely this is IPv4 address on your network interface)
        :param destination_ipv6_address: Destination IPv6 address in DNS answer (most likely this is IPv6 address on your network interface)
        :param source_port: Source UDP port in DNS answer (default: 53 - default port for DNS servers)
        :return: None
        """

        network_filters = {
            'Ethernet': {
                'destination': destination_mac_address
            },
            'IP': {
                'destination-ip': destination_ipv4_address
            },
            'IPv6': {
                'destination-ip': destination_ipv6_address
            },
            'UDP': {
                'source-port': source_port
            }
        }

        sniff = Sniff_raw()

        sniff.start(protocols=['Ethernet', 'IP', 'IPv6', 'UDP', 'DNS'],
                    prn=self._parse_packet,
                    filters=network_filters)

    # _sniff_packets.__annotations__ = {
    #     'destination_mac_address': str,
    #     'destination_ipv4_address': str,
    #     'destination_ipv6_address': str,
    #     'source_port': int,
    #     'return': None
    # }
    # endregion

    # region Send DNS queries to IPv4 NS server
    def _send_ipv4_queries(
            self,
            source_mac_address,  # type: str
            source_ipv4_address,  # type: str
            ns_server_mac_address,  # type: str
            ns_server_ipv4_address,  # type: str
            ns_server_port,  # type: int
            queries,  # type: List[Dict[str, Union[int, str]]]
            send_socket  # type: socket
    ):
        # type: (...) -> None
        """
        Send DNS queries to IPv4 DNS servers
        :param source_mac_address: Source MAC address for DNS query (most likely this is MAC address on your network interface)
        :param source_ipv4_address: Source IPv4 address for DNS query (most likely this is IPv4 address on your network interface)
        :param ns_server_mac_address: DNS server MAC address for DNS query
        :param ns_server_ipv4_address: DNS server IPv4 address for DNS query
        :param ns_server_port: DNS server destination UDP port for DNS query (default: 53)
        :param queries: List of DNS queries for sending (example: [{'type': 1, 'class': 1, 'name': 'www.test.com'}])
        :param send_socket: Raw socket for sending DNS queries
        :return: None
        """

        for query in queries:

            # Set source UDP port and DNS transaction ID for sending DNS query
            udp_source_port = randint(2049, 65535)  # type: int
            dns_transaction_id = randint(1, 65535)  # type: int

            send_socket.send(
                self.dns.make_request_packet(src_mac=source_mac_address,
                                             dst_mac=ns_server_mac_address,
                                             src_ip=source_ipv4_address,
                                             dst_ip=ns_server_ipv4_address,
                                             src_port=udp_source_port,
                                             dst_port=ns_server_port,
                                             tid=dns_transaction_id,
                                             queries=[query]))

    # _send_ipv4_queries.__annotations__ = {
    #     'source_mac_address': str,
    #     'source_ipv4_address': str,
    #     'ns_server_mac_address': str,
    #     'ns_server_ipv4_address': str,
    #     'ns_server_port': int,
    #     'queries': List[Dict[str, Union[int, str]]],
    #     'send_socket': socket,
    #     'return': None
    # }
    # endregion

    # region Send IPv6 DNS queries to IPv6 NS server
    def _send_ipv6_queries(
            self,
            source_mac_address,  # type: str
            source_ipv6_address,  # type: str
            ns_server_mac_address,  # type: str
            ns_server_ipv6_address,  # type: str
            ns_server_port,  # type: int
            queries,  # type: List[Dict[str, Union[int, str]]]
            send_socket  # type: socket
    ):
        # type: (...) -> None
        """
        Send DNS queries to IPv6 DNS servers
        :param source_mac_address: Source MAC address for DNS query (most likely this is MAC address on your network interface)
        :param source_ipv6_address: Source IPv6 address for DNS query (most likely this is IPv6 address on your network interface)
        :param ns_server_mac_address: DNS server MAC address for DNS query
        :param ns_server_ipv6_address: DNS server IPv6 address for DNS query
        :param ns_server_port: DNS server destination UDP port for DNS query (default: 53)
        :param queries: List of DNS queries for sending (example: [{'type': 1, 'class': 1, 'name': 'www.test.com'}])
        :param send_socket: Raw socket for sending DNS queries
        :return: None
        """

        for query in queries:

            # Set source UDP port and DNS transaction ID for sending DNS query
            udp_source_port = randint(2049, 65535)  # type: int
            dns_transaction_id = randint(1, 65535)  # type: int

            send_socket.send(
                self.dns.make_request_packet(src_mac=source_mac_address,
                                             dst_mac=ns_server_mac_address,
                                             src_ip=source_ipv6_address,
                                             dst_ip=ns_server_ipv6_address,
                                             src_port=udp_source_port,
                                             dst_port=ns_server_port,
                                             tid=dns_transaction_id,
                                             queries=[query]))

    # _send_ipv6_queries.__annotations__ = {
    #     'source_mac_address': str,
    #     'source_ipv6_address': str,
    #     'ns_server_mac_address': str,
    #     'ns_server_ipv6_address': str,
    #     'ns_server_port': int,
    #     'queries': List[Dict[str, Union[int, str]]],
    #     'send_socket': socket,
    #     'return': None
    # }
    # endregion

    # region Send DNS queries function
    def _send_queries(
            self,
            send_socket,  # type: socket
            source_mac_address,  # type: str
            source_ipv4_address,  # type: str
            source_ipv6_address,  # type: str
            domain,  # type: str
            ns_servers,  # type: List[Dict[str, str]]
            destination_port=53,  # type: int
            max_threats_count=9,  # type: int
            subdomains=['www'],  # type: List[str]
            queries_type=[1, 28],  # type: List[int]
            queries_class=[1]  # type: List[int]
    ):
        # type: (...) -> None
        """
        Send DNS queries to IPv4/IPv6 DNS servers
        :param send_socket: Raw socket for sending DNS queries
        :param source_mac_address: Source MAC address for DNS query (most likely this is MAC address on your network interface)
        :param source_ipv4_address: Source IPv4 address for DNS query (most likely this is IPv4 address on your network interface)
        :param source_ipv6_address: Source IPv6 address for DNS query (most likely this is IPv6 address on your network interface)
        :param domain: Target domain (example: 'test.com')
        :param ns_servers: List of DNS servers (example: [{'ipv4 address': '8.8.8.8', 'mac address': '01:23:45:67:89:0a'}])
        :param destination_port: UDP destination port (default: 53)
        :param max_threats_count: Maximum threats count (default: 9)
        :param subdomains: List of subdomains (default: ['www'])
        :param queries_type: List of queries type (default: [1, 28]; type 1: A, type 28: AAAA)
        :param queries_class: List of queries class (default: [1]; class 1: IN)
        :return: None
        """

        # DNS query type: 1 (A)
        # DNS query type: 28 (AAAA)
        # DNS query class: 1 (IN)

        # region Init threat manager
        send_threats = ThreadManager(max_threats_count)
        # endregion

        # region Make DNS queries list
        queries = list()
        for subdomain in subdomains:
            for query_type in queries_type:
                for query_class in queries_class:
                    queries.append({
                        'type': query_type,
                        'class': query_class,
                        'name': subdomain + '.' + domain
                    })
        # endregion

        # region Calculate number of DNS queries for one threat
        queries_len = len(queries)
        ipv4_ns_servers_len = 0
        ipv6_ns_servers_len = 0

        for ns_server in ns_servers:
            if 'ipv4 address' in ns_server.keys():
                ipv4_ns_servers_len += 1
            if 'ipv6 address' in ns_server.keys():
                ipv6_ns_servers_len += 1

        if source_ipv6_address is not None:
            queries_len_for_threat = int(
                (queries_len * (ipv4_ns_servers_len + ipv6_ns_servers_len)) /
                max_threats_count) + 1
        else:
            queries_len_for_threat = int(
                (queries_len * ipv4_ns_servers_len) / max_threats_count) + 1
        # endregion

        # region Send DNS queries

        # region Send DNS queries to IPv4 NS servers
        for ns_server in ns_servers:
            if 'ipv4 address' in ns_server.keys():
                for query_index in range(0, queries_len,
                                         queries_len_for_threat):
                    send_threats.add_task(
                        self._send_ipv4_queries, source_mac_address,
                        source_ipv4_address, ns_server['mac address'],
                        ns_server['ipv4 address'], destination_port,
                        queries[query_index:query_index +
                                queries_len_for_threat], send_socket)
        # endregion

        # region Send DNS queries to IPv6 NS servers
        if source_ipv6_address is not None:
            for ns_server in ns_servers:
                if 'ipv6 address' in ns_server.keys():
                    for query_index in range(0, queries_len,
                                             queries_len_for_threat):
                        send_threats.add_task(
                            self._send_ipv6_queries, source_mac_address,
                            source_ipv6_address, ns_server['mac address'],
                            ns_server['ipv6 address'], destination_port,
                            queries[query_index:query_index +
                                    queries_len_for_threat], send_socket)
        # endregion

        # endregion

        # region Wait all threats
        send_threats.wait_for_completion()
        # endregion

    # _send_queries.__annotations__ = {
    #     'send_socket': socket,
    #     'source_mac_address': str,
    #     'source_ipv4_address': str,
    #     'domain': str,
    #     'ns_servers': List[Dict[str, str]],
    #     'destination_port': int,
    #     'max_threats_count': int,
    #     'subdomains': List[str],
    #     'queries_type': List[int],
    #     'queries_class': List[int],
    #     'return': None
    # }
    # endregion

    # region Main function: resolve
    def resolve(
            self,
            ns_servers,  # type: List[Dict[str, str]]
            domain,  # type: str
            subdomains_list=[],  # type: List[str]
            subdomains_file=None,  # type: str
            subdomains_brute=False,  # type: bool
            max_threats_count=10,  # type: int
            udp_destination_port=53,  # type: int
            timeout=30  # type: int
    ):
        # type: (...) -> List[Dict[str, str]]
        """
        DNS resolve all subdomains in target domain
        :param ns_servers: List of DNS servers (example: [{'ipv4 address': '8.8.8.8', 'mac address': '01:23:45:67:89:0a'}])
        :param domain: Target domain (example: 'test.com')
        :param subdomains_list: List of subdomains (example: ['www','ns','mail'])
        :param subdomains_file: Name of file with subdomains (default: None)
        :param subdomains_brute: Brute mode on (auto make list with subdomains) if True, Brute mode off if False (default: False)
        :param max_threats_count: Maximum threats count (default: 10)
        :param udp_destination_port: UDP destination port (default: 53)
        :param timeout: Connection after send all DNS queries (default: 30)
        :return: List of dictionary (example: [{'Domain': 'www.test.com', 'IPv4 address': '1.2.3.4', 'IPv6 address': '-'}])
        """

        try:

            # region Set target domain
            assert not (domain is None or domain == ''), \
                'Target domain is empty, please set target domain in this parameter: ' + self.base.info_text('domain')
            self.domain = domain
            # endregion

            # region Subdomains list
            if len(subdomains_list) > 0:
                self.subdomains = subdomains_list
            # endregion

            # region Subdomains file
            if subdomains_file is not None:
                assert isfile(subdomains_file), \
                    'File with subdomain list:' + self.base.error_text(subdomains_file) + ' not found!'
                with open(subdomains_file) as subdomains_file_descriptor:
                    for subdomain in subdomains_file_descriptor.read(
                    ).splitlines():
                        self.subdomains.append(subdomain)
            # endregion

            # region Subdomains brute
            if subdomains_brute:

                if not self.quiet:
                    self.base.print_info(
                        'Make subdomains list for brute .... ')

                for character1 in self.available_characters:
                    self.subdomains.append(character1)
                    for character2 in self.available_characters:
                        self.subdomains.append(character1 + character2)
                        for character3 in self.available_characters:
                            self.subdomains.append(character1 + character2 +
                                                   character3)
            # endregion

            # region Check length of subdomains list
            assert len(self.subdomains) != 0, \
                'List containing subdomains is empty, please set any of this parameters: ' \
                + self.base.info_text('subdomain_list') + ' or ' \
                + self.base.info_text('subdomain_file') + ' or ' \
                + self.base.info_text('subdomain_brute')
            # endregion

            # region Create raw socket
            raw_socket = socket(AF_PACKET, SOCK_RAW)
            raw_socket.bind((self.network_interface, 0))
            # endregion

            # region Sniff DNS answers
            if not self.quiet:
                self.base.print_info('Start DNS answers sniffer ...')

            threats = ThreadManager(max_threats_count)

            threats.add_task(self._sniff_packets, self.your_mac_address,
                             self.your_ipv4_address, self.your_ipv6_address,
                             udp_destination_port)
            # endregion

            # region Send DNS queries
            if not self.quiet:
                self.base.print_info('Start sending DNS queries, time: ',
                                     str(datetime.now()))

            self._send_queries(send_socket=raw_socket,
                               source_mac_address=self.your_mac_address,
                               source_ipv4_address=self.your_ipv4_address,
                               source_ipv6_address=self.your_ipv6_address,
                               domain=domain,
                               ns_servers=ns_servers,
                               destination_port=udp_destination_port,
                               max_threats_count=int(max_threats_count) - 1,
                               subdomains=self.subdomains)
            # endregion

            # region Timeout
            if not self.quiet:
                self.base.print_info('Wait timeout: ', str(timeout) + ' sec')

            sleep(timeout)
            # endregion

            # region Return results
            return self.results
            # endregion

        except AssertionError as Error:
            self.base.print_error(Error.args[0])
            exit(1)
Ejemplo n.º 3
0
                        help='Number of packets in one iteration (default: 500000)', default=500000)
    parser.add_argument('-k', '--iterations', type=int,
                        help='Number of iterations (default: 100000)', default=100000)

    parser.add_argument('-d', '--domain', type=str, required=True, help='Target domain name (example: test.com)')
    parser.add_argument('-s', '--nsservers', type=str, help='NS servers (example: "ns1.test.com,ns2.test.com")')
    parser.add_argument('-n', '--nsservers_ip', type=str, help='NS servers IP (example: "192.168.0.1,192.168.0.2")')

    parser.add_argument('-N', '--netspoofed', help='Network for IP spoofing (example: "192.168.0.0/24")', default=None)
    parser.add_argument('-P', '--dstport', type=int, help='Set destination port (default: 53)', default=53)
    parser.add_argument('-l', '--pathtodomainlist', type=str, help='Set path to file with domain list', default=None)

    args = parser.parse_args()

    eth = Ethernet_raw()
    dns = DNS_raw()

    if args.pathtodomainlist is not None:
        print("Create your DNS name list...")
        try:
            with open(args.pathtodomainlist, "r") as domain_list:
                for domain_name in domain_list:
                    NAMES.append(domain_name[:-1])
            print(" List of domains len: " + str(len(NAMES)))
            print(" List of domains created: " + NAMES[0] + " ... " + NAMES[len(NAMES) - 1])

        except:
            print("File: " + args.pathtodomainlist + " not found!")
            exit(1)

    if args.interface is None:
Ejemplo n.º 4
0
class DnsServer:

    # region Set variables
    base = None
    sniff = None
    dns = None

    rawSocket = None

    network_interface = None
    port = 0
    your_mac_address = None
    your_ip_address = None
    your_ipv6_addresses = None

    target_ip_address = None
    target_ipv6_address = None

    fake_answers = False
    fake_domains = []
    fake_addresses = {}
    no_such_names = []

    DNS_QUERY_TYPES = []
    A_DNS_QUERY = 0
    AAAA_DNS_QUERY = 0

    success_domains = []

    # endregion

    # region Init
    def __init__(self):
        self.base = Base()
        self.sniff = Sniff_raw()
        self.dns = DNS_raw()

        self.rawSocket = socket(AF_PACKET, SOCK_RAW)

        self.port = 53
        self.A_DNS_QUERY = 1
        self.AAAA_DNS_QUERY = 28

    # endregion

    # region Get first IPv4 or IPv6 address of domain
    @staticmethod
    def _get_domain_address(query_name, query_type=1):

        # Set proto
        if query_type == 28:
            proto = AF_INET6
        else:
            proto = AF_INET

        try:
            # Get list of addresses
            addresses = getaddrinfo(query_name, None, proto)

            # Return first address from list
            return [addresses[0][4][0]]

        except gaierror:

            # Could not resolve name
            return None

    # endregion

    # region DNS reply function
    def _reply(self, request):

        # region This request is DNS query
        if 'DNS' in request.keys():

            for request_query in request['DNS']['queries']:

                # region Get DNS query type
                query_type = request_query['type']
                # endregion

                # region Type of DNS query type: A or AAAA
                if query_type in self.DNS_QUERY_TYPES:

                    try:

                        # region Local variables
                        query_class = request_query['class']
                        answer = []
                        addresses = None
                        # endregion

                        # region Create query list
                        if request_query['name'].endswith("."):
                            query_name = request_query['name'][:-1]
                        else:
                            query_name = request_query['name']

                        query = [{
                            "type": query_type,
                            "class": query_class,
                            "name": query_name
                        }]
                        # endregion

                        # region Script arguments condition check

                        # region Variable fake_answers is True
                        if self.fake_answers:
                            addresses = self.fake_addresses[query_type]
                        # endregion

                        # region Variable fake_answers is False
                        else:

                            # region Fake domains list is set
                            if len(self.fake_domains) > 0:

                                # region Fake domains list is set and DNS query name in fake domains list
                                if query_name in self.fake_domains:

                                    # region A DNS query
                                    if query_type == self.A_DNS_QUERY:

                                        # Fake IPv4 is set
                                        if self.A_DNS_QUERY in self.fake_addresses.keys(
                                        ):
                                            if len(self.fake_addresses[
                                                    self.A_DNS_QUERY]) > 0:
                                                addresses = self.fake_addresses[
                                                    self.A_DNS_QUERY]

                                        # Fake IPv4 is NOT set
                                        else:
                                            addresses = self._get_domain_address(
                                                query_name, query_type)

                                    # endregion

                                    # region AAAA DNS query
                                    if query_type == self.AAAA_DNS_QUERY:

                                        # Fake IPv6 is set
                                        if self.AAAA_DNS_QUERY in self.fake_addresses.keys(
                                        ):
                                            if len(self.fake_addresses[
                                                    self.AAAA_DNS_QUERY]) > 0:
                                                addresses = self.fake_addresses[
                                                    self.AAAA_DNS_QUERY]

                                        # Fake IPv6 is NOT set
                                        else:
                                            addresses = self._get_domain_address(
                                                query_name, query_type)

                                    # endregion

                                # endregion

                                # region Fake domains list is set and DNS query name NOT in fake domains list
                                else:
                                    addresses = self._get_domain_address(
                                        query_name, query_type)
                                # endregion

                            # endregion

                            # region Fake domains list is NOT set
                            else:

                                # region A DNS query
                                if query_type == self.A_DNS_QUERY:

                                    # Fake IPv4 is set
                                    if self.A_DNS_QUERY in self.fake_addresses.keys(
                                    ):
                                        if len(self.fake_addresses[
                                                self.A_DNS_QUERY]) > 0:
                                            addresses = self.fake_addresses[
                                                self.A_DNS_QUERY]

                                    # Fake IPv4 is NOT set
                                    else:
                                        addresses = self._get_domain_address(
                                            query_name, query_type)

                                # endregion

                                # region AAAA DNS query
                                if query_type == self.AAAA_DNS_QUERY:

                                    # Fake IPv6 is set
                                    if self.AAAA_DNS_QUERY in self.fake_addresses.keys(
                                    ):
                                        if len(self.fake_addresses[
                                                self.AAAA_DNS_QUERY]) > 0:
                                            addresses = self.fake_addresses[
                                                self.AAAA_DNS_QUERY]

                                    # Fake IPv6 is NOT set
                                    else:
                                        addresses = self._get_domain_address(
                                            query_name, query_type)

                                # endregion

                            # endregion

                        # endregion

                        # endregion

                        # region Query name in no_such_names list
                        if query_name in self.no_such_names:
                            addresses = ['no such name']
                        # endregion

                        # region Answer addresses is set

                        if addresses is not None:

                            # region Create answer list
                            dns_answer_flags = 0x8580

                            for address in addresses:
                                if address == 'no such name':
                                    dns_answer_flags = 0x8183
                                    answer = []
                                    break
                                else:
                                    answer.append({
                                        "name": query_name,
                                        "type": query_type,
                                        "class": query_class,
                                        "ttl": 0xffff,
                                        "address": address
                                    })

                            # endregion

                            # region Make dns answer packet
                            if 'IP' in request.keys():
                                dns_answer_packet = self.dns.make_response_packet(
                                    src_mac=request['Ethernet']['destination'],
                                    dst_mac=request['Ethernet']['source'],
                                    src_ip=request['IP']['destination-ip'],
                                    dst_ip=request['IP']['source-ip'],
                                    src_port=53,
                                    dst_port=request['UDP']['source-port'],
                                    tid=request['DNS']['transaction-id'],
                                    flags=dns_answer_flags,
                                    queries=query,
                                    answers_address=answer)

                            elif 'IPv6' in request.keys():
                                dns_answer_packet = self.dns.make_response_packet(
                                    src_mac=request['Ethernet']['destination'],
                                    dst_mac=request['Ethernet']['source'],
                                    src_ip=request['IPv6']['destination-ip'],
                                    dst_ip=request['IPv6']['source-ip'],
                                    src_port=53,
                                    dst_port=request['UDP']['source-port'],
                                    tid=request['DNS']['transaction-id'],
                                    flags=dns_answer_flags,
                                    queries=query,
                                    answers_address=answer)

                            else:
                                dns_answer_packet = None
                            # endregion

                            # region Send DNS answer packet
                            if dns_answer_packet is not None:
                                self.rawSocket.send(dns_answer_packet)
                            # endregion

                            # region Print info message
                            if 'IP' in request.keys():
                                if query_type == 1:
                                    if query_name in self.success_domains:
                                        self.base.print_success(
                                            "DNS query from: ",
                                            request['IP']['source-ip'], " to ",
                                            request['IP']['destination-ip'],
                                            " type: ", "A", " domain: ",
                                            query_name, " answer: ",
                                            (", ".join(addresses)))
                                    else:
                                        self.base.print_info(
                                            "DNS query from: ",
                                            request['IP']['source-ip'], " to ",
                                            request['IP']['destination-ip'],
                                            " type: ", "A", " domain: ",
                                            query_name, " answer: ",
                                            (", ".join(addresses)))
                                if query_type == 28:
                                    if query_name in self.success_domains:
                                        self.base.print_success(
                                            "DNS query from: ",
                                            request['IP']['source-ip'], " to ",
                                            request['IP']['destination-ip'],
                                            " type: ", "AAAA", " domain: ",
                                            query_name, " answer: ",
                                            (", ".join(addresses)))
                                    else:
                                        self.base.print_info(
                                            "DNS query from: ",
                                            request['IP']['source-ip'], " to ",
                                            request['IP']['destination-ip'],
                                            " type: ", "AAAA", " domain: ",
                                            query_name, " answer: ",
                                            (", ".join(addresses)))

                            if 'IPv6' in request.keys():
                                if query_type == 1:
                                    if query_name in self.success_domains:
                                        self.base.print_success(
                                            "DNS query from: ",
                                            request['IPv6']['source-ip'],
                                            " to ",
                                            request['IPv6']['destination-ip'],
                                            " type: ", "A", " domain: ",
                                            query_name, " answer: ",
                                            (", ".join(addresses)))
                                    else:
                                        self.base.print_info(
                                            "DNS query from: ",
                                            request['IPv6']['source-ip'],
                                            " to ",
                                            request['IPv6']['destination-ip'],
                                            " type: ", "A", " domain: ",
                                            query_name, " answer: ",
                                            (", ".join(addresses)))
                                if query_type == 28:
                                    if query_name in self.success_domains:
                                        self.base.print_success(
                                            "DNS query from: ",
                                            request['IPv6']['source-ip'],
                                            " to ",
                                            request['IPv6']['destination-ip'],
                                            " type: ", "AAAA", " domain: ",
                                            query_name, " answer: ",
                                            (", ".join(addresses)))
                                    else:
                                        self.base.print_info(
                                            "DNS query from: ",
                                            request['IPv6']['source-ip'],
                                            " to ",
                                            request['IPv6']['destination-ip'],
                                            " type: ", "AAAA", " domain: ",
                                            query_name, " answer: ",
                                            (", ".join(addresses)))
                            # endregion

                        # endregion

                    except:
                        pass
                # endregion

        # endregion

    # endregion

    # region Start server
    def listen(self,
               listen_network_interface,
               listen_port=53,
               target_mac_address=None,
               target_ip_address=None,
               target_ipv6_address=None,
               fake_answers=False,
               fake_ip_addresses=[],
               fake_ipv6_addresses=[],
               fake_domains=[],
               no_such_names=[],
               listen_ipv6=False,
               disable_ipv4=False,
               disable_ipv6=False,
               success_domains=[]):

        # region Set success domains
        self.success_domains = success_domains
        # endregion

        # region Set fake answers
        self.fake_answers = fake_answers
        # endregion

        # region Set DNS_QUERY_TYPES
        if listen_ipv6:
            if disable_ipv4:
                self.DNS_QUERY_TYPES = [28]
            else:
                if disable_ipv6:
                    self.DNS_QUERY_TYPES = [1]
                else:
                    self.DNS_QUERY_TYPES = [1, 28]
        else:
            self.DNS_QUERY_TYPES = [1]
        # endregion

        # region Set listen network interface
        self.network_interface = listen_network_interface
        # endregion

        # region Set listen UDP port
        if listen_port != 53:
            if 0 < listen_port < 65535:
                self.port = listen_port
            else:
                self.base.print_error("Bad value in `listen_port`: ",
                                      str(listen_port),
                                      "; listen UDP port must be in range: ",
                                      "1 - 65534")
                exit(1)
        # endregion

        # region Get your MAC, IP and IPv6 addresses
        self.your_mac_address = self.base.get_netiface_mac_address(
            self.network_interface)
        if self.your_mac_address is None:
            self.base.print_error("Network interface: ",
                                  self.network_interface,
                                  " do not have MAC address!")
            exit(1)

        self.your_ip_address = self.base.get_netiface_ip_address(
            self.network_interface)
        if self.your_ip_address is None:
            self.base.print_error("Network interface: ",
                                  self.network_interface,
                                  " do not have IP address!")
            exit(1)

        if listen_ipv6:
            self.your_ipv6_addresses = self.base.get_netiface_ipv6_link_address(
                self.network_interface)
            if len(self.your_ipv6_addresses) == 0:
                self.base.print_error("Network interface: ",
                                      self.network_interface,
                                      " do not have IPv6 link local address!")
                exit(1)
            else:
                self.fake_addresses[self.AAAA_DNS_QUERY] = [
                    self.your_ipv6_addresses
                ]
        else:
            self.fake_addresses[self.AAAA_DNS_QUERY] = None
        # endregion

        # region Bind raw socket
        self.rawSocket.bind((self.network_interface, 0))
        # endregion

        # region Set fake addresses
        if len(fake_ip_addresses) > 0:
            self.fake_addresses[self.A_DNS_QUERY] = fake_ip_addresses
        else:
            if not disable_ipv4:
                self.fake_addresses[self.A_DNS_QUERY] = [self.your_ip_address]

        if len(fake_ipv6_addresses) > 0:
            self.fake_addresses[self.AAAA_DNS_QUERY] = fake_ipv6_addresses
            if disable_ipv4:
                self.DNS_QUERY_TYPES = [self.AAAA_DNS_QUERY]
            else:
                self.DNS_QUERY_TYPES = [self.A_DNS_QUERY, self.AAAA_DNS_QUERY]
        else:
            if self.fake_answers:
                if listen_ipv6:
                    self.fake_addresses[self.AAAA_DNS_QUERY] = [
                        self.your_ipv6_addresses
                    ]
        # endregion

        # region Set fake domains and "no such names" lists
        self.fake_domains = fake_domains
        self.no_such_names = no_such_names
        # endregion

        # region Check target IPv4 address
        if target_ip_address is not None:
            if not self.base.ip_address_validation(target_ip_address):
                self.base.print_error("Bad target IPv4 address: ",
                                      target_ip_address)
                exit(1)
            else:
                self.target_ip_address = target_ip_address
        # endregion

        # region Check target IPv6 address
        if target_ipv6_address is not None:
            if not self.base.ipv6_address_validation(target_ipv6_address):
                self.base.print_error("Bad target IPv6 address: ",
                                      target_ipv6_address)
                exit(1)
            else:
                self.target_ipv6_address = target_ipv6_address
        # endregion

        # region Sniffing DNS requests

        # region Set network filter
        network_filters = {}

        if target_mac_address is not None:
            network_filters['Ethernet'] = {'source': target_mac_address}
        else:
            network_filters['Ethernet'] = {'not-source': self.your_mac_address}

        if self.target_ip_address is not None:
            network_filters['IP'] = {'source-ip': self.target_ip_address}

        if self.target_ipv6_address is not None:
            network_filters['IPv6'] = {'source-ip': self.target_ipv6_address}

        network_filters['IP'] = {'not-source-ip': '127.0.0.1'}
        network_filters['UDP'] = {'destination-port': self.port}
        # endregion

        # region Clear fake_answers list
        if not self.fake_answers:
            if len(fake_ipv6_addresses) == 0:
                del self.fake_addresses[self.AAAA_DNS_QUERY]
            if len(fake_ip_addresses) == 0:
                del self.fake_addresses[self.A_DNS_QUERY]
        # endregion

        # region Start sniffer
        if listen_ipv6:
            if disable_ipv4:
                self.sniff.start(protocols=['IPv6', 'UDP', 'DNS'],
                                 prn=self._reply,
                                 filters=network_filters)
            else:
                self.sniff.start(protocols=['IP', 'IPv6', 'UDP', 'DNS'],
                                 prn=self._reply,
                                 filters=network_filters)
        else:
            self.sniff.start(protocols=['IP', 'UDP', 'DNS'],
                             prn=self._reply,
                             filters=network_filters)
Ejemplo n.º 5
0
# region Authorship information
__author__ = 'Vladimir Ivanov'
__copyright__ = 'Copyright 2019, Raw-packet Project'
__credits__ = ['']
__license__ = 'MIT'
__version__ = '0.0.4'
__maintainer__ = 'Vladimir Ivanov'
__email__ = '*****@*****.**'
__status__ = 'Development'
# endregion

# region Global variables
arp = ARP_raw()
dhcp = DHCP_raw()
dns = DNS_raw()

network_interface = "eth0"
ethernet_src = "00:0c:29:4f:e6:9c"
ethernet_dst = "00:50:56:c0:00:01"
ip_src = "192.168.119.139"
ip_dst = "192.168.119.1"

global_socket = socket(AF_PACKET, SOCK_RAW)
global_socket.bind((network_interface, 0))

execution_time = {}
# endregion


# region Send ARP packets in raw-packet