def create_server(self): self._server = UDPServer(self.listen_responses, None, socket=self._soc) self._server_coro = self._server.run()
class MDNSClient(): def __init__(self, timeout=5): self._mcast_addr = ('224.0.0.251', 5353) self.timeout = timeout self._query_TID = os.urandom(2) self._soc = None self._server_coro = None self._query_packet = None self._loop = asyncio.get_event_loop() self.result = {} def setup_socket(self): mcast_addr = ipaddress.ip_address(self._mcast_addr[0]) self._soc = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) self._soc.setblocking( False) #SUPER IMPORTANT TO SET THIS FOR ASYNCIO!!!! self._soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self._soc.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255) self._soc.bind(self._mcast_addr) mreq = struct.pack("=4sl", mcast_addr.packed, socket.INADDR_ANY) self._soc.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) def create_server(self): self._server = UDPServer(self.listen_responses, None, socket=self._soc) self._server_coro = self._server.run() def send_queries(self, query_names): qstns = [] for qry in query_names: qstns.append(DNSQuestion.construct(qry, DNSType.PTR, DNSClass.IN)) self._query_packet = DNSPacket.construct(TID=self._query_TID, response=DNSResponse.REQUEST, questions=qstns) self._soc.sendto(self._query_packet.toBytes(), self._mcast_addr) @asyncio.coroutine def stop_loop(self): yield from asyncio.sleep(self.timeout) self._loop.stop() return def run(self, query_names): self.setup_socket() self.create_server() self.send_queries(query_names) self._loop.create_task(self.stop_loop()) try: self._loop.run_until_complete(self._server_coro) except RuntimeError as e: if str(e) == 'Event loop stopped before Future completed.': pass else: raise (e) except Exception as e: traceback.print_exc() print(e) return self.result def listen_responses(self, reader, writer): msg = DNSPacket.from_buffer(reader.buff) if msg.QR == DNSResponse.RESPONSE: for ans in msg.Answers: if ans.domainname.name[0] == '_': #walking the tree... print('Walk the tree: %s' % ans.domainname.name) qst = DNSQuestion.construct(ans.domainname.name, DNSType.PTR, DNSClass.IN) qry = DNSPacket.construct(TID=os.urandom(2), response=DNSResponse.REQUEST, questions=[qst]) self._soc.sendto(qry.toBytes(), self._mcast_addr) #else: # print(ans.domainname) name = None for ans in msg.Additionals: if ans.TYPE == DNSType.A or ans.TYPE == DNSType.AAAA: if ans.NAME.name not in self.result: self.result[ans.NAME.name] = {} self.result[ans.NAME.name][ans.ipaddress] = [] name = ans.NAME.name for ans in msg.Additionals: if ans.TYPE == DNSType.SRV: for ip in self.result[name]: self.result[name][ip].append(ans.Port)
class MDNSClient(): def __init__(self, timeout=5): self._mcast_addr = ('224.0.0.251', 5353) self.timeout = timeout self._query_names = {} self._soc = None self._server_coro = None self._query_packet = None self._loop = asyncio.get_event_loop() self.result = {} def setup_socket(self): mcast_addr = ipaddress.ip_address(self._mcast_addr[0]) self._soc = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) self._soc.setblocking( False) #SUPER IMPORTANT TO SET THIS FOR ASYNCIO!!!! self._soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self._soc.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255) self._soc.bind(self._mcast_addr) mreq = struct.pack("=4sl", mcast_addr.packed, socket.INADDR_ANY) self._soc.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) def create_server(self): self._server = UDPServer(self.listen_responses, None, socket=self._soc) self._server_coro = self._server.run() def send_queries(self, query_names): qstns = [] for qry in query_names: for dtype in [DNSType.A, DNSType.AAAA]: if qry.find('.local') == -1: qry += '.local' qstns.append(DNSQuestion.construct(qry, dtype, DNSClass.IN)) tid = os.urandom(2) if qry not in self._query_names: #apparently there are no transaction IDs in mdns... self._query_names[qry] = 1 self._query_packet = DNSPacket.construct( TID=tid, response=DNSResponse.REQUEST, questions=qstns) self._soc.sendto(self._query_packet.to_bytes(), self._mcast_addr) @asyncio.coroutine def stop_loop(self): yield from asyncio.sleep(self.timeout) self._loop.stop() return def run(self, query_names): self.setup_socket() self.create_server() self.send_queries(query_names) self._loop.create_task(self.stop_loop()) try: self._loop.run_until_complete(self._server_coro) except RuntimeError as e: if str(e) == 'Event loop stopped before Future completed.': pass else: raise (e) except Exception as e: traceback.print_exc() print(e) return self.result def listen_responses(self, reader, writer): msg = DNSPacket.from_buffer(reader.buff) if msg.QR == DNSResponse.RESPONSE: for ans in msg.Answers: if ans.TYPE == DNSType.A or ans.TYPE == DNSType.AAAA: if ans.NAME.name in self._query_names: if ans.NAME.name not in self.result: self.result[ans.NAME.name] = [] self.result[ans.NAME.name].append(ans.ipaddress)
class DHCPClient(): def __init__(self): self._query_TID = os.urandom(4) self._soc = None self._server_coro = None self._loop = asyncio.get_event_loop() self.result = {} def setup_socket(self): self._soc = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) self._soc.setblocking(False)#SUPER IMPORTANT TO SET THIS FOR ASYNCIO!!!! self._soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self._soc.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) self._soc.bind(('', 68)) def create_server(self): self._server = UDPServer(self.listen_responses, None, sock = self._soc) self._server_coro = self._server.run() def send_discover(self, options_extra = None): options = [DHCPOptDHCPMESSAGETYPE.construct(DHCPOptMessageType.DHCPDISCOVER)] if options_extra is not None: options += options_extra options.append(DHCPOptEND.construct()) dhcpquery = DHCPMessage.construct(self._query_TID, DHCPOpcode.BOOTREQUEST, options) self._soc.sendto(dhcpquery.to_bytes(), ('255.255.255.255', 67)) @asyncio.coroutine def stop_loop(self): yield from asyncio.sleep(1) self._loop.stop() return def run(self, options = None): self.setup_socket() self.create_server() self.send_discover(options) self._loop.create_task(self.stop_loop()) try: self._loop.run_until_complete(self._server_coro) except RuntimeError as e: if str(e) == 'Event loop stopped before Future completed.': pass else: raise(e) except Exception as e: traceback.print_exc() print(e) def listen_responses(self, reader, writer): msg = DHCPMessage.from_buffer(reader.buff) if msg.xid == self._query_TID: for option in msg.options: if option.code == 53 and option.msgtype == DHCPOptMessageType.DHCPOFFER: print('Got offer! IP address offered: %s' % (str(msg.yiaddr))) print(repr(msg)) self._loop.create_task(self.send_request(msg)) if option.code == 53 and option.msgtype == DHCPOptMessageType.DHCPACK: print('Got ACK!: %s' % (str(msg.yiaddr))) print(repr(msg)) #self._loop.create_task(self.send_request(msg)) else: #not a message for us pass @asyncio.coroutine def send_request(self, offer, request_options_extra = None): options = [DHCPOptDHCPMESSAGETYPE.construct(DHCPOptMessageType.DHCPREQUEST)] options.append(DHCPOptREQUESTEDIPADDRESS.construct(offer.yiaddr)) options.append(DHCPOptSERVERIDENTIFIER.construct(offer.siaddr)) options.append(DHCPOptPARAMETERREQUEST.construct(list(range(2,61)))) if request_options_extra is not None: options += request_options_extra options.append(DHCPOptEND.construct()) dhcprequest = DHCPMessage.construct(self._query_TID, DHCPOpcode.BOOTREQUEST, options, yiaddr=offer.yiaddr, siaddr=offer.siaddr) self._soc.sendto(dhcprequest.to_bytes(), ('255.255.255.255', 67))
class LLMNRClient(): def __init__(self, ipversion=4, ifname='eth0', timeout=1): self._mcast_ip4 = ipaddress.ip_address('224.0.0.252') self._mcast_ip6 = ipaddress.ip_address('FF02:0:0:0:0:0:1:3') self._timeout = timeout self._ipversion = ipversion self._ifname = ifname self._query_TIDs = [] self._soc = None self._server_coro = None self._query_packet = None self._loop = asyncio.get_event_loop() self.result = {} def setup_socket(self): if self._ipversion == 4: self._mcast_addr = (str(self._mcast_ip4), 5355) self._soc = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) self._soc.setblocking( False) #SUPER IMPORTANT TO SET THIS FOR ASYNCIO!!!! self._soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self._soc.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255) self._soc.bind(('', 5355)) mreq = struct.pack("=4sl", self._mcast_ip4.packed, socket.INADDR_ANY) self._soc.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) else: interface_index = socket.if_nametoindex(self._ifname) self._soc = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, socket.IPPROTO_UDP) self._soc.bind(('::', 5355, 0, interface_index)) self._soc.setsockopt( socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, struct.pack('16sI', self._mcast_ip6.packed, interface_index)) self._soc.setblocking( False) #SUPER IMPORTANT TO SET THIS FOR ASYNCIO!!!! self._mcast_addr = (str(self._mcast_ip6), 5355, 0, interface_index) def create_server(self): self._server = UDPServer(self.listen_responses, None, socket=self._soc) self._server_coro = self._server.run() def send_queries(self, query_names): qstns = [] for qry in query_names: self.result[qry] = [] tid = os.urandom(2) self._query_TIDs.append(tid) qstns.append(DNSQuestion.construct(qry, DNSType.A, DNSClass.IN)) self._query_packet = LLMNRPacket.construct( TID=tid, response=LLMNRResponse.REQUEST, questions=qstns) self._soc.sendto(self._query_packet.to_bytes(), self._mcast_addr) @asyncio.coroutine def stop_loop(self): yield from asyncio.sleep(self._timeout) self._loop.stop() return def run(self, query_names): self.setup_socket() self.create_server() self.send_queries(query_names) self._loop.create_task(self.stop_loop()) try: self._loop.run_until_complete(self._server_coro) except RuntimeError as e: if str(e) == 'Event loop stopped before Future completed.': pass else: raise (e) except Exception as e: traceback.print_exc() print(e) self.print_result() def print_result(self): print('NAME\tIP\t\tRESPONSE_FROM') for qry in self.result: for res in self.result[qry]: for src in res: print('%s\t%s\t%s' % (qry, res[src], src)) def listen_responses(self, reader, writer): msg = LLMNRPacket.from_buffer(reader.buff) if msg.QR == LLMNRResponse.RESPONSE: if msg.TransactionID in self._query_TIDs: for ans in msg.Answers: if ans.TYPE == DNSType.A or ans.TYPE == DNSType.AAAA: self.result[ans.NAME.name].append( {writer._addr[0]: str(ans.ipaddress)}) else: print('[!] Got response with unknown TID!')