def generateResponseWithPortNumber(response, sock, addr, times): ''' Generate the Port Number. ''' try: portNumbers = [random.randint(1, 65536) for i in range(times)] portNumbers.sort() round_ = 1 while round_ <= 1: Helper.printOnScreenAlways("Round: " + str(round_), MSG_TYPES.RESULT) index = 0 for portNumber in portNumbers: # range (1, 10000): # 1000 time should be enoght index += 1 Helper.printOnScreenAlways( "R: %d - %d- %d" % (round_, index, portNumber), MSG_TYPES.YELLOW) lst = list(addr) lst[1] = portNumber addr = tuple(lst) sock.sendto(response, addr) round_ = round_ + 1 except Exception as ex: logging.error('DNSFunctions - generateResponseWithPortNumber: \n %s ' % traceback.format_exc()) # </editor-fold>
def makeDirectories(): ''' make the directories in case they are missing. ''' try: if not os.path.exists('JSON'): os.makedirs('JSON') os.makedirs('JSON/CheckingRequests') os.makedirs('JSON/NormalRequests') else: if not os.path.exists('JSON/CheckingRequests'): os.makedirs('JSON/CheckingRequests') if not os.path.exists('JSON/NormalRequests'): os.makedirs('JSON/NormalRequests') if not os.path.exists('Logs'): os.makedirs('Logs') os.makedirs('Logs/Errors') if not os.path.exists('Logs/Errors'): os.makedirs('Logs/Errors') except Exception as ex: Helper.printOnScreenAlways(ex, term.Color.RED) logging.error('DNSFunctions - makeDirectories: %s' % traceback.format_exc())
def generateResponseWithRequestId(response, sock, addr, times): #,expectedID=0,resp=''): ''' Generate the Request Id ''' try: round_ = 1 while round_ <= 1: Helper.printOnScreenAlways("Round: " + str(round_), MSG_TYPES.RESULT) requestIds = [random.randint(1, 65536) for i in range(times)] requestIds.sort() index = 0 hafltimes = times / 2 for requestId in requestIds: #range (1, 10000): # 1000 time should be enoght index += 1 Helper.printOnScreenAlways( "R: %d - %d- %d" % (round_, index, requestId), MSG_TYPES.YELLOW) TransactionID_Byte = (requestId).to_bytes(2, byteorder='big') finalResponse = TransactionID_Byte + response sock.sendto(finalResponse, addr) round_ = round_ + 1 except Exception as ex: logging.error('DNSFunctions - generateResponseWithRequestId:\n %s ' % traceback.format_exc())
def printModifiedDate(): try: filename = os.path.basename(__file__) os.path.abspath(os.path.dirname(__file__)) (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime) = os.stat(filename) return time.ctime(mtime) except Exception as ex: Helper.printOnScreenAlways("run_DNS -printModifedDate: %s" % ex, MSG_TYPES.ERROR)
def run(argv): modifiedDate = printModifiedDate() DNSFunctions.makeDirectories() Helper.initLogger(level=logging.ERROR, enableConsole=False) DNSFunctions.printLogo(version=VERSION, modifyDate=modifiedDate) DNSFunctions.killprocess(PORT) DNSFunctions.setDebuggingMode(DEBUG) if argv.s is True: ip = socket.gethostbyname(socket.gethostname()) else: ip = IP_ADDRESS_LOCAL main(argv, ip)
def loadFakeZone(): ''' load all the fake zones that we have when the DNS server starts up, and put them into memory. ''' global FAKEZONEDATA jsonZone = {} # dictionary zFile = 'Zones/FakeZone.zone' printDebugMode(zFile) # Debug with open(zFile) as zonedata: data = json.load(zonedata) zoneName = data['$origin'] jsonZone[zoneName] = data FAKEZONEDATA = jsonZone Helper.printOnScreenAlways( " =--------------**Fake Zone file has been loaded**--------------=", MSG_TYPES.RESULT)
def storeHTTPRequestJSON(time, srcIP, baseUrl, mode='none'): """Help for the bar method of Foo classes""" date = Helper.getTime(TIME_FORMAT.DATE) if mode == 'check': file = JsonRequestsPATHCheck + '_' + date + '.json' else: # TODO: need refactoring - make it more abstract file = JsonRequestsPATH + '_' + date + '.json' jsons = {} if (os.path.exists(file) ) != True: # check if the file exist, if not create it. with open(file, 'w+') as jsonfile: json.dump(' ', jsonfile) else: with open(file, 'r') as jsonfile: jsons = json.load(jsonfile) with open(file, 'w') as jsonfile: DNSRequestNodes = { 'Request': { 'ID': str(len(jsons) + 1), 'Time': time, 'SrcIP': srcIP, 'Url': baseUrl, } } jsons[str(len(jsons) + 1)] = DNSRequestNodes # Write into Json file json.dump(jsons, jsonfile)
def logDNSRequest(counter, status, recordType, requestId, srcIP, srcPort, domain, modifiedDomain='', mode='none'): ''' Logging all the DNS requests. ''' date = Helper.getTime(TIME_FORMAT.FULL) printedRow = '' if status == 'ERROR': if modifiedDomain == '': printedRow = ( '%s - %d: ** ERROR ** : | RecordType: %s | RequestId: %s | SrcIP: %s | SrcPort: %d | Domain: %s ' % (date, counter, recordType, requestId, srcIP, srcPort, domain)) else: printedRow = ( '%s - %d: ** ERROR ** : | RecordType: %s | RequestId: %s | SrcIP: %s | SrcPort: %d | Domain: %s | ModifiedDomain: %s' % (date, counter, recordType, requestId, srcIP, srcPort, domain, modifiedDomain)) printStatus = MSG_TYPES.ERROR elif status == 'OKAY': if modifiedDomain == '': printedRow = ( '%s - %d: | RecordType: %s | RequestId: %s | SrcIP: %s | SrcPort: %d | Domain: %s ' % (date, counter, recordType, requestId, srcIP, srcPort, domain)) else: printedRow = ( '%s - %d: | RecordType: %s | RequestId: %s | SrcIP: %s | SrcPort: %d | Domain: %s | ModifiedDomain: %s' % (date, counter, recordType, requestId, srcIP, srcPort, domain, modifiedDomain)) printStatus = MSG_TYPES.RESULT loggingData(printedRow) return (printedRow, printStatus)
def main(argv, IP): global FORCE_NOT_RESPONSE_MEG letterCaseRandomize = argv.rcase port = argv.port sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind((IP, port)) printPortAndIP(IP, port) if letterCaseRandomize: printNcase() ADVERSARY_Mode = argv.adversary FORCE_NOT_RESPONSE_MODE = argv.dont if FORCE_NOT_RESPONSE_MODE: Helper.printOnScreenAlways( ' ***** NO RESPONSE MODE IS ACTIVATED *****', MSG_TYPES.YELLOW) DNSFunctions.loadRealZone() try: if not ADVERSARY_Mode: # keep listening #DNSFunctions.loadRealZone() while 1: data, addr = sock.recvfrom(512) response, allowResponse = DNSFunctions.getResponse( data, addr, letterCaseRandomize, forceNotResponseMode=FORCE_NOT_RESPONSE_MODE) if allowResponse: sock.sendto(response, addr) elif ADVERSARY_Mode: # attacking mode Helper.printOnScreenAlways( ' ***** ADVERSARY MODE IS ACTIVATED *****', MSG_TYPES.YELLOW) DNSFunctions.loadFakeZone() setAdversaryModetask(argv.task) # keep listening while 1: data, addr = sock.recvfrom(512) if RANDOMIZE_PORT is True: ## try all the possible Port Number 1 to 65556 response = DNSFunctions.getResponse( data, addr, case_sensitive=False, adversaryMode=ADVERSARY_Mode, withoutRequestId=False) # we get the correct response. DNSFunctions.generateResponseWithPortNumber( response, sock, addr, NUMBER_OF_TRIES ) # brute force all the possible port number elif RANDOMIZE_REQUEST_ID is True: ## try all the possible request IDs 1 to 65556 response = DNSFunctions.getResponse( data, addr, case_sensitive=False, adversaryMode=ADVERSARY_Mode, withoutRequestId=True ) # forge response without request ID, later we forge the ID and combine it with the whole response DNSFunctions.generateResponseWithRequestId( response, sock, addr, NUMBER_OF_TRIES ) # brute force # we get the response once without Tre_id elif RANDOMIZE_BOTH: # response = DNSFunctions.getResponse(data, addr, case_sensitive=False, adversaryMode=ADVERSARY_Mode, # withoutRequestId=True) # forge response without request ID, later we forge the ID and combine it with the whole response # DNSFunctions.generat pass except Exception as ex: Helper.loggingError(str('ERROR: main ' + traceback.format_exc())) Helper.printOnScreenAlways("\nERROR: Terminated!!! :" + str(ex), MSG_TYPES.ERROR)
def printNcase(): Helper.printOnScreenAlways( " ***** Randomise Domain Name Letters Capitalisation is ACTIVATED *****", MSG_TYPES.YELLOW)
def getForgedResponse(data, addr, case_sensitive=True): # ********************************** DNS Header # Transaction ID TransactionID_Byte = data[:2] TransactionID = '' for byte in TransactionID_Byte: TransactionID += hex(byte)[2:] if DEBUG is True: # Debug mode only print('ID:') print(TransactionID) # FLAGS Flags = getFlags(data[2:4]) if DEBUG is True: # Debug mode only print(Flags) # Question Count, how many questions in the zone file QDCOUNT = RECORD_TYPES.A.value # b'\x00\x01' # dns has one question records, recordType, domainName, recStatus = getRecs(data[12:]) # Answer Count # ANCOUNT = len(getRecs(data[12:])[0]).to_bytes(2, byteorder='big') # 12 bytes to skip the header ANCOUNT = len(records).to_bytes( 2, byteorder='big') # 12 bytes to skip the header # Name server nodeCount NSCOUNT = (0).to_bytes(2, byteorder='big') # Additional nodeCount ARCOUNT = (0).to_bytes(2, byteorder='big') #***** # BUILD THE HEADER WITHOUT THE TRANSACTION ID/REQUEST ID, AFTER FORGE IT, WILL BE ADDED TO THE HEADER #***** DNSHeader = TransactionID_Byte + Flags + QDCOUNT + ANCOUNT + NSCOUNT + ARCOUNT DNSHeader = Flags + QDCOUNT + ANCOUNT + NSCOUNT + ARCOUNT if DEBUG is True: dnsH = '' print('DNS HEADER: ' + str(DNSHeader)) for byte in DNSHeader: dnsH += hex(byte)[2:] print(dnsH) # ********************************** DNS Question # records, recordType, domainName = getRecs(data[12:]) global COUNTER COUNTER += 1 transactionID = str(int(TransactionID, 16)) domain = '.'.join(map(str, domainName))[:-1] srcIP = addr[0] srcPort = addr[1] status = 'Okay' time = Helper.getTime(TIME_FORMAT.TIME) if case_sensitive is True: domainName = getLetterCaseSwapped(domainName) modifiedDomain = '.'.join(map(str, domainName))[:-1] printedRow, printStatus = logDNSRequest(counter=COUNTER, status=recStatus, recordType=recordType, requestId=transactionID, srcIP=srcIP, srcPort=srcPort, domain=domain, modifiedDomain=modifiedDomain, mode='none') Helper.printOnScreenAlways(printedRow, printStatus) if 'check_' in domain.lower(): storeDNSRequestJSON(status=status, time=time, recordType=recordType, transactionID=transactionID, srcIP=addr[0], srcPort=str(addr[1]), domain=domain, modifiedDomain=modifiedDomain, mode='check') else: storeDNSRequestJSON(status=status, time=time, recordType=recordType, transactionID=transactionID, srcIP=addr[0], srcPort=str(addr[1]), domain=domain, modifiedDomain=modifiedDomain) else: printedRow, printStatus = logDNSRequest(counter=COUNTER, status=recStatus, recordType=recordType, requestId=transactionID, srcIP=srcIP, srcPort=srcPort, domain=domain, mode='none') Helper.printOnScreenAlways(printedRow, printStatus) if 'check_' in domain.lower(): storeDNSRequestJSON(status=status, time=time, recordType=recordType, transactionID=transactionID, srcIP=addr[0], srcPort=str(addr[1]), domain=domain, mode='check') else: storeDNSRequestJSON(status=status, time=time, recordType=recordType, transactionID=transactionID, srcIP=addr[0], srcPort=str(addr[1]), domain=domain) DNSQuestion = buildQuestion(domainName, recordType) if DEBUG is True: print('DNSQuestion: ' + str(DNSQuestion)) # DNS Body DNSBody = b'' for record in records: DNSBody += recordToBytes(domainName, recordType, record['ttl'], record['value']) if DEBUG is True: print(DNSBody) return DNSHeader + DNSQuestion + DNSBody
def getResponse(data, addr, case_sensitive=False, adversaryMode=False, withoutRequestId=False, forceNotResponseMode=False): ''' Build the DNS Response ''' # ********************************** DNS Header # Transaction ID TransactionID_Byte = data[:2] TransactionID = '' for byte in TransactionID_Byte: TransactionID += hex(byte)[2:] if DEBUG is True: # Debug mode only print('ID:') print(TransactionID) # FLAGS Flags = getFlags(data[2:4]) if DEBUG is True: # Debug mode only print(Flags) # Question Count, how many questions in the zone file QDCOUNT = RECORD_TYPES.A.value #b'\x00\x01' # dns has one question domain, questionType = getQuestionDomain(data[12:]) if adversaryMode is True: # load the fake zone zone = getFakeZone(domain) else: #load the real zone zone = getZone(domain) records, recordType, domainName, recStatus = getRecs( zone=zone, domain=domain, questionType=questionType) # Answer Count #ANCOUNT = len(getRecs(data[12:])[0]).to_bytes(2, byteorder='big') # 12 bytes to skip the header ANCOUNT = len(records).to_bytes( 2, byteorder='big') # 12 bytes to skip the header # Name server nodeCount NSCOUNT = (0).to_bytes(2, byteorder='big') # Additional nodeCount ARCOUNT = (0).to_bytes(2, byteorder='big') RealDNSHeader_Test = b' ' # for testing if withoutRequestId is False: DNSHeader = TransactionID_Byte + Flags + QDCOUNT + ANCOUNT + NSCOUNT + ARCOUNT else: # BUILD THE HEADER WITHOUT THE TRANSACTION ID/REQUEST ID, AFTER FORGE IT, WILL BE ADDED TO THE HEADER DNSHeader = Flags + QDCOUNT + ANCOUNT + NSCOUNT + ARCOUNT RealDNSHeader_Test = TransactionID_Byte + Flags + QDCOUNT + ANCOUNT + NSCOUNT + ARCOUNT if DEBUG is True: dnsH = '' print('DNS HEADER: ' + str(DNSHeader)) print('DNS HEADER_test: ' + str(RealDNSHeader_Test)) for byte in DNSHeader: dnsH += hex(byte)[2:] print('DNSHeader:' + dnsH) # ********************************** DNS Question #records, recordType, domainName = getRecs(data[12:]) global COUNTER COUNTER += 1 transactionID = str(int(TransactionID, 16)) srcIP = addr[0] srcPort = addr[1] domain = '.'.join(map(str, domainName))[:-1] status = 'Okay' time = Helper.getTime(TIME_FORMAT.TIME) # TODO: implement a method that distinguishes sendRequests if they have been called from TORMAPPER if case_sensitive is True and 'check_' in domain.lower( ): # need to be more dynamic modifiedDomain = domain # without permutation if 're_check_' not in domain.lower(): # re_check without permutation domainName = getLetterCaseSwapped(domainName) modifiedDomain = '.'.join(map(str, domainName))[:-1] printedRow, printStatus = logDNSRequest(counter=COUNTER, status=recStatus, recordType=recordType, requestId=transactionID, srcIP=srcIP, srcPort=srcPort, domain=domain, modifiedDomain=modifiedDomain, mode='none') Helper.printOnScreenAlways(printedRow, printStatus) if 'check_' in domain.lower(): storeDNSRequestJSON(status=status, time=time, recordType=recordType, transactionID=transactionID, srcIP=addr[0], srcPort=str(addr[1]), domain=domain, modifiedDomain=modifiedDomain, mode='check') else: storeDNSRequestJSON(status=status, time=time, recordType=recordType, transactionID=transactionID, srcIP=addr[0], srcPort=str(addr[1]), domain=domain, modifiedDomain=modifiedDomain) else: printedRow, printStatus = logDNSRequest(counter=COUNTER, status=recStatus, recordType=recordType, requestId=transactionID, srcIP=srcIP, srcPort=srcPort, domain=domain, mode='none') Helper.printOnScreenAlways(printedRow, printStatus) if 'check_' in domain.lower(): storeDNSRequestJSON(status=status, time=time, recordType=recordType, transactionID=transactionID, srcIP=addr[0], srcPort=str(addr[1]), domain=domain, mode='check') else: storeDNSRequestJSON(status=status, time=time, recordType=recordType, transactionID=transactionID, srcIP=addr[0], srcPort=str(addr[1]), domain=domain) DNSQuestion = buildQuestion(domainName, recordType) if DEBUG is True: print('DNSQuestion: ' + str(DNSQuestion)) response = True if forceNotResponseMode: if FORCE_NOT_RESPONSE_MEG in domain: response = False # ********************************** DNS Body DNSBody = b'' for record in records: DNSBody += recordToBytes(domainName, recordType, record['ttl'], record['value']) if DEBUG is True: print('DNSBody: ' + str(DNSBody)) print(str(DNSHeader) + '\n' + str(DNSQuestion) + '\n' + str(DNSBody)) return ((DNSHeader + DNSQuestion + DNSBody), response ) #, (RealDNSHeader_Test + DNSQuestion + DNSBody)
def storeDNSRequestJSONText(status, time, recordType, transactionID, srcIP, srcPort, domain, modifiedDomain='none', mode='none'): ''' Logging all the DNS request in json format ''' date = Helper.getTime(TIME_FORMAT.DATE) if mode == 'check': file = JSON_REQUESTS_PATH_CHECK + '_' + date + '.json' else: # TODO: need refactoring - make it more abstract file = JSON_REQUESTS_PATH + '_' + date + '.json' jsons = {} if (os.path.exists(file) ) != True: # check if the file exist, if not create it. with open(file, 'w+') as jsonfile: json.dump(' ', jsonfile) else: with open(file, 'r') as jsonfile: jsons = json.load(jsonfile) if domain[-1:] == '.': domain = domain[:-1] row ='"%d": { "Request" : {' \ '"ID" : str(len(jsons) + 1),"Time": %s,' \ '"Status": %s,' \ '"TransactionID": %s,' \ '"RecordType": %s,' \ '"SrcIP": %s,' \ '"SrcPort": %s,' \ '"Domain": %s,' \ '"modifiedDomain": %s } },' %(id, time, status, transactionID, recordType, srcIP, srcPort, domain, modifiedDomain) with open(file, 'w') as jsonfile: DNSRequestNodes = { 'Request': { 'ID': str(len(jsons) + 1), 'Time': time, 'Status': status, 'TransactionID': transactionID, 'RecordType': recordType, 'SrcIP': srcIP, 'SrcPort': srcPort, 'Domain': domain, 'modifiedDomain': modifiedDomain, } } jsons[str(len(jsons) + 1)] = DNSRequestNodes # Write into Json file json.dump(jsons, jsonfile)
def storeDNSRequestJSON(status, time, recordType, transactionID, srcIP, srcPort, domain, modifiedDomain='none', mode='none'): """Help for the bar method of Foo classes""" date = Helper.getTime(TIME_FORMAT.DATE) pathDirt = '' if mode == 'check': path = JSON_REQUESTS_PATH_CHECK else: # TODO: need refactoring - make it more abstract path = JSON_REQUESTS_PATH pathFile = ('%s_%s.json' % (path, date)) jsons = {} if (os.path.exists(pathFile) ) != True: # check if the file exist, if not create it. with open(pathFile, 'w+') as jsonfile: # not exist json.dump(' ', jsonfile) else: try: with open(pathFile, 'r') as jsonfile: jsons = json.load(jsonfile) except ValueError as er: logging.error( 'DNSFunction - storeDNSRequestJSON - JSON invalid - file: %s : %s' % (path, str(er))) os.rename(pathFile, ('%s_%s_error_%d.json' % (path, date, random.randint(1, 50)))) with open(pathFile, 'a+') as jsonfile: json.dump(' ', jsonfile) if domain[-1:] == '.': domain = domain[:-1] with open(pathFile, 'w') as jsonfile: DNSRequestNodes = { 'Request': { 'ID': str(len(jsons) + 1), 'Time': time, 'Status': status, 'TransactionID': transactionID, 'RecordType': recordType, 'SrcIP': srcIP, 'SrcPort': srcPort, 'Domain': domain, 'modifiedDomain': modifiedDomain, } } jsons[str(len(jsons) + 1)] = DNSRequestNodes # Write into Json file json.dump(jsons, jsonfile)