def _listener(self): '''Listen for transport messages on the signaling socket. The default maximum packet size to receive is 1500 bytes. The interval argument specifies how often should the sock be checked for close, default is 180 s. This is a generator function and should be invoked as multitask.add(u._listener()).''' self.app.status.append('Listener Generator Initiated') try: while self.sock and self._stack: try: data, remote = (yield multitask.recvfrom(self.sock, self.max_size, timeout=self.interval)) logger.debug('received[%d] from %s\n%s' % (len(data), remote, data)) if self.state != self.FUZZING and self.state != self.FUZZING_COMPETED: self._stack.received(data, remote) else: m = rfc3261_IPv6.Message() try: if self.crash_fuzz == self.WAIT_CRSH_CHK and self.crash_porbe == self.CRASH_PROBE_REC: # If response to fuzz is received # m._parse(data) self.app.fuzzResponse[ self.fuzz_index] = data.split( '\n', 1)[0].replace('\r', '') self.crash_porbe = self.FUZZ_RECV elif self.crash_fuzz == self.WAIT_CRSH_CHK and self.crash_porbe == self.CRASH_PROBE_SENT: # If response to probe received self._stack.received(data, remote) self.app.probeResponse[ self.fuzz_index] = data.split( '\n', 1)[0].replace('\r', '') except ValueError, E: # TODO: send 400 response to non-ACK request logger.debug('Error in received message:', E) logger.debug(traceback.print_exc()) except multitask.Timeout: if self.state == self.FUZZING and self.crash_detect: print( bcolors.FAIL + "Crash detected!" + bcolors.ENDC + " It seems that we found a server crash. Server is not responding. If this is a false-positive you can use --fuzz-crash-no-stop option to prevent the app stop at crash detection." ) self.app.printResults() self.app.stop() except GeneratorExit: pass except: print 'User._listener exception', (sys and sys.exc_info() or None) traceback.print_exc() raise logger.debug('terminating User._listener()')
def _listener(self): '''Listen for transport messages on the signaling socket. The default maximum packet size to receive is 1500 bytes. The interval argument specifies how often should the sock be checked for close, default is 180 s. This is a generator function and should be invoked as multitask.add(u._listener()).''' self.app.status.append('Listener Generator Initiated') try: while self.sock and self._stack: try: data, remote = (yield multitask.recvfrom(self.sock, self.max_size, timeout=self.interval)) logger.debug('received[%d] from %s\n%s'%(len(data),remote,data)) if self.state != self.FUZZING and self.state != self.FUZZING_COMPETED: self._stack.received(data, remote) else: m = rfc3261_IPv6.Message() try: if self.crash_fuzz==self.WAIT_CRSH_CHK and self.crash_porbe==self.CRASH_PROBE_REC: # If response to fuzz is received # m._parse(data) self.app.fuzzResponse[self.fuzz_index] = data.split('\n', 1)[0].replace('\r','') self.crash_porbe=self.FUZZ_RECV elif self.crash_fuzz==self.WAIT_CRSH_CHK and self.crash_porbe==self.CRASH_PROBE_SENT: # If response to probe received self._stack.received(data, remote) self.app.probeResponse[self.fuzz_index] = data.split('\n', 1)[0].replace('\r','') except ValueError, E: # TODO: send 400 response to non-ACK request logger.debug('Error in received message:', E) logger.debug(traceback.print_exc()) except multitask.Timeout: if self.state == self.FUZZING and self.crash_detect: print (bcolors.FAIL+"Crash detected!"+bcolors.ENDC +" It seems that we found a server crash. Server is not responding. If this is a false-positive you can use --fuzz-crash-no-stop option to prevent the app stop at crash detection.") self.app.printResults() self.app.stop() except GeneratorExit: pass except: print 'User._listener exception', (sys and sys.exc_info() or None); traceback.print_exc(); raise logger.debug('terminating User._listener()')
def _send(self, data, addr): # generator version if self._snifferGen: # Reconfig socket needed because of scapy ------------------- if rfc2396_IPv6.isIPv6(self.remoteTarget): # Unstable if self.app.options.int_ip == '0.0.0.0': self.app.options.int_ip= '::1' sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM if self.app.options.transport == self.UDP else socket.SOCK_STREAM) else: sock = socket.socket(type=socket.SOCK_DGRAM if self.app.options.transport == self.UDP else socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind((self.app.options.int_ip, (self.app.options.port+1) if self.app.options.transport == self.TLS else self.app.options.port)) self.sock = sock #------------------------------------------------------------ try: logger.debug('sending[%d] to %s\n%s'%(len(data), addr, data)) if self.sock: if self.sock.type == socket.SOCK_STREAM: try: remote = self.sock.getpeername() if remote != addr: logger.debug('connected to wrong addr', remote, 'but sending to', addr) except socket.error: # not connected, try connecting try: self.sock.connect(addr) except socket.error: logger.debug('failed to connect to', addr) try: yield self.sock.send(data) except socket.error: logger.debug('socket error in send') elif self.sock.type == socket.SOCK_DGRAM: try: yield self.sock.sendto(data, addr) except socket.error: logger.debug('socket error in sendto' ) else: logger.debug('invalid socket type', self.sock.type) except AttributeError: pass
def _fuzzing(self): # Msg to Fuzz generator --------- fuzzers = {'InviteCommonFuzzer': 'INVITE_COMMON', 'InviteStructureFuzzer': 'INVITE_STRUCTURE', 'InviteRequestLineFuzzer': 'INVITE_REQUEST_LINE','InviteOtherFuzzer': 'INVITE_OTHER', 'CANCELFuzzer': 'CANCEL', 'REGISTERFuzzer': 'REGISTER','SUBSCRIBEFuzzer': 'SUBSCRIBE', 'NOTIFYFuzzer': 'NOTIFY', 'ACKFuzzer': 'ACK'} def fuzzingCtrl(fuzz_index): if self.state == self.FUZZING: import datetime def log_perc_completed(i, partials, total=self.mutations): partials = map(int,(partials.split(','))) for partial in partials: if i == (partial*total/100): logger.info(str((datetime.datetime.now()-self.start_fuzz_time).total_seconds()*1000)+' msec'+': '+str(int((total*partial/100)//1))+'/'+str(total)+' ('+str(int((partial)//1))+'%) messages sent') if not self.start_fuzz_time: self.start_fuzz_time = datetime.datetime.now() if self.crash_detect: log_perc_completed(fuzz_index,'1,2,4,8,10,20,30,40,50,60,70,80,90,100') else: log_perc_completed(fuzz_index,'25,50,75,100') def _createMutableMessage(): # Msg to Fuzz generator --------- if not self.fuzzer == 'All': mutable_msg = s_get(fuzzers.get(self.fuzzer)) else: mutable_msg = s_get(fuzzers.get('INVITE_COMMON')) return mutable_msg def _createFuzzerMsgGen(mutable_msg): def replaceDefaults(rendered_msg): from random import Random import string # branch self.curr_invite_branch = ''.join(Random().sample(string.ascii_lowercase+string.digits, 32)) rendered_msg = rendered_msg.replace('somebranchvalue', self.curr_invite_branch) rendered_msg = rendered_msg.replace('somefromtagvalue', self.curr_invite_branch) rendered_msg = rendered_msg.replace('somecallidvalue', self.curr_invite_branch) # This stuff is new in this function and should be moved elsewhere # Works fine here for now though rendered_msg = rendered_msg.replace('TARGET_USER', self.remoteParty.uri.user) rendered_msg = rendered_msg.replace('HOST', self.remoteParty.uri.host) rendered_msg = rendered_msg.replace('USER', self.localParty.uri.user) rendered_msg = rendered_msg.replace('LOCAL_IP', self.localParty.uri.host) rendered_msg = rendered_msg.replace('192.168.96.69', self.localParty.uri.host) rendered_msg = rendered_msg.replace('192.168.99.99', self.localParty.uri.host) rendered_msg = rendered_msg.replace('PORT', str(self.localParty.uri.port)) rendered_msg = rendered_msg.replace(':password', '') return rendered_msg if not self.fuzzer == 'All': for i in range(min(self.mutations, self.fuzz_max_msgs)): mutable_msg.mutate() m = replaceDefaults(mutable_msg.render()) yield (m) else: msg_counter = 0 for item in fuzzers: mutable_msg = s_get(fuzzers.get(item)) for i in range(mutable_msg.num_mutations()): msg_counter += 1 if msg_counter < min(self.mutations, self.fuzz_max_msgs): mutable_msg.mutate() m = replaceDefaults(mutable_msg.render()) yield (m) # Stop listener if no crash detection is been used if self.listenerOff: self._listenerGen.close() # Dest Address addr = self.remoteTarget.uri if addr and isinstance(addr, rfc2396_IPv6.URI): if not addr.host: raise ValueError, 'No host in destination uri' addr = (addr.host, addr.port or self.transport.type == 'tls' and self.transport.secure and 5061 or 5060) mutable_msg = _createMutableMessage() # Msg generator if not self.fuzzer == 'All': self.mutations = mutable_msg.num_mutations() else: self.mutations = 0 for item in fuzzers: self.mutations += s_get(fuzzers.get(item)).num_mutations() Fuzz_Generator = _createFuzzerMsgGen(mutable_msg) if self.audit_file_name: self.audit_file_name = open(self.audit_file_name, 'w') print "Fuzzing %s messages to %s" % (self.mutations, addr) try: if self.sock: if self.sock.type == socket.SOCK_STREAM: pass elif self.sock.type == socket.SOCK_DGRAM: while True: try: data = str(Fuzz_Generator.next()) if len(data) > 9216: data = data[:9216] try: # SEND FUZZ MSG self.sock.sendto(data, addr) # Index self.fuzz_index += 1 fuzzingCtrl(self.fuzz_index) if self.audit_file_name: self.audit_file_name.write("Index "+str(self.fuzz_index)+"\n--\n"+data+"\n--\n\n") self.crash_fuzz=self.WAIT_CRSH_CHK # if crash detect => wait until crash detection is completed #print '1. Fuzz sent' while (self.crash_detect and self.crash_fuzz!=self.WAIT_FUZZ): yield multitask.sleep(1) except socket.error: logger.debug('socket error in sendto' ) except StopIteration: self.state = self.FUZZING_COMPETED raise StopIteration() yield else: logger.debug('invalid socket type', self.sock.type) except AttributeError: pass
def _fuzzing(self): # Msg to Fuzz generator --------- fuzzers = { 'InviteCommonFuzzer': 'INVITE_COMMON', 'InviteStructureFuzzer': 'INVITE_STRUCTURE', 'InviteRequestLineFuzzer': 'INVITE_REQUEST_LINE', 'InviteOtherFuzzer': 'INVITE_OTHER', 'CANCELFuzzer': 'CANCEL', 'REGISTERFuzzer': 'REGISTER', 'SUBSCRIBEFuzzer': 'SUBSCRIBE', 'NOTIFYFuzzer': 'NOTIFY', 'ACKFuzzer': 'ACK' } def fuzzingCtrl(fuzz_index): if self.state == self.FUZZING: import datetime def log_perc_completed(i, partials, total=self.mutations): partials = map(int, (partials.split(','))) for partial in partials: if i == (partial * total / 100): logger.info( str((datetime.datetime.now() - self.start_fuzz_time).total_seconds() * 1000) + ' msec' + ': ' + str(int((total * partial / 100) // 1)) + '/' + str(total) + ' (' + str(int((partial) // 1)) + '%) messages sent') if not self.start_fuzz_time: self.start_fuzz_time = datetime.datetime.now() if self.crash_detect: log_perc_completed( fuzz_index, '1,2,4,8,10,20,30,40,50,60,70,80,90,100') else: log_perc_completed(fuzz_index, '25,50,75,100') def _createMutableMessage(): # Msg to Fuzz generator --------- if not self.fuzzer == 'All': mutable_msg = s_get(fuzzers.get(self.fuzzer)) else: mutable_msg = s_get(fuzzers.get('INVITE_COMMON')) return mutable_msg def _createFuzzerMsgGen(mutable_msg): def replaceDefaults(rendered_msg): from random import Random import string # branch self.curr_invite_branch = ''.join(Random().sample( string.ascii_lowercase + string.digits, 32)) rendered_msg = rendered_msg.replace('somebranchvalue', self.curr_invite_branch) rendered_msg = rendered_msg.replace('somefromtagvalue', self.curr_invite_branch) rendered_msg = rendered_msg.replace('somecallidvalue', self.curr_invite_branch) # This stuff is new in this function and should be moved elsewhere # Works fine here for now though rendered_msg = rendered_msg.replace('TARGET_USER', self.remoteParty.uri.user) rendered_msg = rendered_msg.replace('HOST', self.remoteParty.uri.host) rendered_msg = rendered_msg.replace('USER', self.localParty.uri.user) rendered_msg = rendered_msg.replace('LOCAL_IP', self.localParty.uri.host) rendered_msg = rendered_msg.replace('192.168.96.69', self.localParty.uri.host) rendered_msg = rendered_msg.replace('192.168.99.99', self.localParty.uri.host) rendered_msg = rendered_msg.replace( 'PORT', str(self.localParty.uri.port)) rendered_msg = rendered_msg.replace(':password', '') return rendered_msg if not self.fuzzer == 'All': for i in range(min(self.mutations, self.fuzz_max_msgs)): mutable_msg.mutate() m = replaceDefaults(mutable_msg.render()) yield (m) else: msg_counter = 0 for item in fuzzers: mutable_msg = s_get(fuzzers.get(item)) for i in range(mutable_msg.num_mutations()): msg_counter += 1 if msg_counter < min(self.mutations, self.fuzz_max_msgs): mutable_msg.mutate() m = replaceDefaults(mutable_msg.render()) yield (m) # Stop listener if no crash detection is been used if self.listenerOff: self._listenerGen.close() # Dest Address addr = self.remoteTarget.uri if addr and isinstance(addr, rfc2396_IPv6.URI): if not addr.host: raise ValueError, 'No host in destination uri' addr = (addr.host, addr.port or self.transport.type == 'tls' and self.transport.secure and 5061 or 5060) mutable_msg = _createMutableMessage() # Msg generator if not self.fuzzer == 'All': self.mutations = mutable_msg.num_mutations() else: self.mutations = 0 for item in fuzzers: self.mutations += s_get(fuzzers.get(item)).num_mutations() Fuzz_Generator = _createFuzzerMsgGen(mutable_msg) if self.audit_file_name: self.audit_file_name = open(self.audit_file_name, 'w') print "Fuzzing %s messages to %s" % (self.mutations, addr) try: if self.sock: if self.sock.type == socket.SOCK_STREAM: pass elif self.sock.type == socket.SOCK_DGRAM: while True: try: data = str(Fuzz_Generator.next()) if len(data) > 9216: data = data[:9216] try: # SEND FUZZ MSG self.sock.sendto(data, addr) # Index self.fuzz_index += 1 fuzzingCtrl(self.fuzz_index) if self.audit_file_name: self.audit_file_name.write( "Index " + str(self.fuzz_index) + "\n--\n" + data + "\n--\n\n") self.crash_fuzz = self.WAIT_CRSH_CHK # if crash detect => wait until crash detection is completed #print '1. Fuzz sent' while (self.crash_detect and self.crash_fuzz != self.WAIT_FUZZ): yield multitask.sleep(1) except socket.error: logger.debug('socket error in sendto') except StopIteration: self.state = self.FUZZING_COMPETED raise StopIteration() yield else: logger.debug('invalid socket type', self.sock.type) except AttributeError: pass
def _flood(self): from helper_functions import generateExtentions, loopExtentionsDictionary # Flood info messages --------- def floodingCtrl(): if self.state == self.FLOODING: import datetime def log_perc_completed(i, partials, total=self.flood_num): partials = map(int,(partials.split(','))) for partial in partials: if i == (partial*total/100): logger.info(str((datetime.datetime.now()-self.start_flood_time).total_seconds()*1000)+' msec'+': '+str(int((total*partial/100)//1))+'/'+str(total)+' ('+str(int((partial)//1))+'%) messages sent') if not self.start_flood_time: self.start_flood_time = datetime.datetime.now() self.flood_msg += 1 log_perc_completed(self.flood_msg,'25,50,75,100') # Msg to flood generator --------- def _createBaseMessage(): if self.flood_msg_file: with open (self.flood_msg_file, "r") as file_txt: file_txt=file_txt.read() m = rfc3261_IPv6.Message() try: if self.flood_noparse: m = file_txt else: m = m._parse(file_txt.rstrip()+'\r\n\r\n\r\n') except ValueError, E: pass # TODO: send 400 response to non-ACK request else: m = self._ua.createRequest(self.flood_method) m.To = rfc3261_IPv6.Header(str(self.app.options.to.uri), 'To') m.Contact = rfc3261_IPv6.Header(str(self._stack.uri), 'Contact') m.Contact.value.uri.user = self.localParty.uri.user m.Expires = rfc3261_IPv6.Header(str(self.app.options.register_interval), 'Expires') return m def _createFloodMsgGen(message_generated): if self.app.options.modify_extentions and not self.flood_noparse: if self.app.options.ExtDictionary is not None: try: dictionary = open(self.app.options.ExtDictionary,'r') except IOError: logger.error( "Could not open %s" % self.app.options.ExtDictionary ) exit(1) self.ExtensionsGenerator = loopExtentionsDictionary(dictionary) else: self.ExtensionsGenerator = generateExtentions(*(self.app.options.ExtRange,self.app.options.ExtZeropadding,self.app.options.ExtTemplate,self.app.options.ExtDefaults)) self.message_generated = message_generated while True: message_generated = self.message_generated # Modify message_generated: extension (To,From), tag, Call-ID extension = self.ExtensionsGenerator.next() if message_generated.method == "INVITE": if self.app.options.registrar_ip != self.app.options.to.uri.host: SourceFakeAddr = self.app.options.registrar_ip else: SourceFakeAddr = str(self.app.options.to.uri.host).split('.') SourceFakeAddr[3] = str(random.randint(0,254)) SourceFakeAddr = ".".join(SourceFakeAddr) message_generated.From.value.uri.user = message_generated.From.value.displayName = extension message_generated.From.value.uri.host = SourceFakeAddr else: message_generated.From.value.uri.user = message_generated.From.value.displayName = message_generated.To.value.uri.user = message_generated.To.value.displayName = extension message_generated.From.tag=str(random.randint(0,2**31)) message_generated['Call-ID'] = rfc3261_IPv6.Header(str(random.randint(0,2**31)) + '@' + (message_generated.From.value.uri.host or 'localhost'), 'Call-ID') yield (message_generated) else: while True: yield (message_generated) # Dest Address addr = self.remoteTarget.uri if addr and isinstance(addr, rfc2396_IPv6.URI): if not addr.host: raise ValueError, 'No host in destination uri' addr = (addr.host, addr.port or self.transport.type == 'tls' and self.transport.secure and 5061 or 5060) # Msg generator base_msg = _createBaseMessage() flood_msg = _createFloodMsgGen(base_msg) if self.flood_noparse: print "Flooding %s NOPARSED messages to %s" % (self.flood_num, addr) else: print "Flooding %s %s messages to %s" % (self.flood_num, base_msg.method, addr) try: if self.sock: if self.sock.type == socket.SOCK_STREAM: try: remote = self.sock.getpeername() if remote != addr: logger.debug('connected to wrong addr', remote, 'but sending to', addr) except socket.error: # not connected, try connecting try: self.sock.connect(addr) except socket.error: logger.debug('failed to connect to', addr) try: for i in range(self.flood_num): logger.debug('[Msg:%s/%s] sending[%d] to %s\n%s'%((self.flood_msg+1),self.flood_num,len(data), addr, '')) self.sock.send(data) floodingCtrl() self.app.stop() yield raise StopIteration() except socket.error: logger.debug('socket error in send') elif self.sock.type == socket.SOCK_DGRAM: try: for i in range(self.flood_num): data = str(flood_msg.next()) logger.debug('[Msg:%s/%s] sending[%d] to %s\n%s'%((self.flood_msg+1),self.flood_num,len(data), addr, '')) logger.debug(data) self.sock.sendto(data, addr) floodingCtrl() self.app.stop() yield raise StopIteration() except socket.error: logger.debug('socket error in sendto' ) else: logger.debug('invalid socket type', self.sock.type) except AttributeError: pass
# Msg generator base_msg = _createBaseMessage() flood_msg = _createFloodMsgGen(base_msg) if self.flood_noparse: print "Flooding %s NOPARSED messages to %s" % (self.flood_num, addr) else: print "Flooding %s %s messages to %s" % (self.flood_num, base_msg.method, addr) try: if self.sock: if self.sock.type == socket.SOCK_STREAM: try: remote = self.sock.getpeername() if remote != addr: logger.debug('connected to wrong addr', remote, 'but sending to', addr) except socket.error: # not connected, try connecting try: self.sock.connect(addr) except socket.error: logger.debug('failed to connect to', addr) try: for i in range(self.flood_num): logger.debug('[Msg:%s/%s] sending[%d] to %s\n%s' % ((self.flood_msg + 1), self.flood_num, len(data), addr, '')) self.sock.send(data) floodingCtrl() self.app.stop() yield raise StopIteration()