Last active
May 12, 2020 04:00
-
-
Save idkiller/b9a8b0b83a69c3cefc5a3369cc655f98 to your computer and use it in GitHub Desktop.
python mDNS / DNS-SD sniff tool (Parsing DNS-SD packet!)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # -*- coding: utf-8 -*- | |
| import socket | |
| import struct | |
| from time import gmtime, strftime | |
| import re | |
| #import binascii | |
| import string | |
| class packetSniff(): | |
| def __init__(self): | |
| self.hostip = '224.0.0.251' | |
| def analDNSPacket(self, packet): | |
| now = strftime("%Y-%M-%d %H:%M:%S", gmtime()) | |
| recvHeader = struct.unpack_from('!HHHHHH', packet[:12]) | |
| recvData = packet[12:].split(b'\x00', 1) | |
| flag_QnA = recvHeader[1] & 0b1000000000000000 | |
| queryType, queryClass = struct.unpack('!HH', recvData[1][:4]) | |
| rData = packet[12:] | |
| name = self.parseDomainName(rData[:rData.index(b'\x00')], packet) | |
| #if not name.startswith('._jenkins'): | |
| # return | |
| if flag_QnA == 0 : | |
| print('[DNS Query]------------------------------------') | |
| else : | |
| print('[DNS Response]---------------------------------') | |
| print('[*] Time : ' + now) | |
| print('[+] Transaction ID : ' + str(hex(recvHeader[0]))) | |
| print('[+] Flags : ' + str(hex(recvHeader[1]))) | |
| print('[+] Number of queries : ' + str(hex(recvHeader[2]))) | |
| print('[+] Number of authoritative : ' + str(hex(recvHeader[3]))) | |
| print('[+] Number of additional record : ' + str(hex(recvHeader[4]))) | |
| print('[+] Query Name : ' + name) | |
| print('[+] Query Type : ' + str(hex(queryType))) + '('+str(queryType)+')' | |
| print('[+] Query Class : ' + str(hex(queryClass))) | |
| if flag_QnA != 0: | |
| ttl, rdlength = struct.unpack('!IH', recvData[1][4:10]) | |
| print('[+] TTL : ' + str(ttl)) | |
| print('[+] RDLength : ' + str(rdlength)) | |
| rdata = recvData[1][10: 10 + rdlength] | |
| print('[+] DATA : ') | |
| if queryType == 16: # TXT | |
| index = 0 | |
| while index < len(rdata): | |
| length = ord(rdata[index]) | |
| data = rdata[index+1:index+1+length] | |
| print(' ' + data) | |
| index += length + 1 | |
| elif queryType == 1: # A | |
| print(' Address : ' + '.'.join([str(ord(x)) for x in rdata]) ) | |
| elif queryType == 28: # AAAA | |
| addr = list(struct.unpack('!HHHHHHHH', rdata)) | |
| print(' Address : ' + '.'.join([str(a) for a in addr])) | |
| elif queryType == 33: # SRV | |
| priority, weight, port, length = struct.unpack('!HHHB', rdata[:7]) | |
| print(' Priority : ' + str(priority)) | |
| print(' Weight : ' + str(weight)) | |
| print(' Port : ' + str(port)) | |
| print(' Length : ' + str(length)) | |
| #print(' Target : ' + rdata[7:length+7]) | |
| print(' Target : ' + self.parseDomainName(rdata[7:], packet)) | |
| elif queryType == 12: # PTR | |
| print(' Domain : ' + self.parseDomainName(rdata, packet)) | |
| else: | |
| print ' '.join('{:02x}'.format(ord(x)) for x in rdata) | |
| print ' '.join('{:>2}'.format(x) if x in string.printable else '□ ' for x in rdata) | |
| print('-----------------------------------------------') | |
| def parseLabel(self, data): | |
| chars = [] | |
| i = 0 | |
| size = 0 | |
| while i < len(data) and data[i] != b'\x00': | |
| size = ord(data[i]) | |
| chars.append(data[i+1:i+1+size].encode('utf-8')) | |
| i += size + 1 | |
| return '.'.join(chars) | |
| def parseDomainName(self, rdata, packet): | |
| if ord(rdata[-2]) & 0xc0 == 0xc0: | |
| index = (ord(rdata[-2]) & 0x3f) << 8 | ord(rdata[-1]) | |
| return self.parseLabel(rdata[:-2]) + '.' + self.parseLabel(packet[index:]) | |
| else: | |
| return self.parseLabel(rdata) | |
| def start(self): | |
| rawsock = socket.socket(family=socket.AF_INET, type=socket.SOCK_RAW, proto=17) | |
| rawsock.bind((self.hostip, 0)) | |
| # rawsock.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) | |
| print('[*] Start Sniffer Process!') | |
| while(True): | |
| packet, address = rawsock.recvfrom(65565) | |
| srcport = struct.unpack_from('!H', packet[20:22])[0] | |
| dstport = struct.unpack_from('!H', packet[22:24])[0] | |
| if(srcport == 5353 or dstport == 5353): | |
| now = strftime("%H:%M:%S", gmtime()) | |
| self.analDNSPacket(packet[28:]) | |
| if __name__ == '__main__': | |
| obj = packetSniff() | |
| obj.start() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment