def readSymbol(self, timeout=EmptySymbol.defaultReceptionTimeout()): """Read from the abstraction layer a message and abstract it into a message. The timeout parameter represents the amount of time (in millisecond) above which no reception of a message triggers the reception of an :class:`netzob.Common.Models.Vocabulary.EmptySymbol.EmptySymbol`. If timeout set to None or to a negative value means it always wait for the reception of a message. :keyword timeout: the time above which no reception of message triggers the reception of an :class:`netzob.Common.Models.Vocabulary.EmptySymbol.EmptySymbol` :type timeout: :class:`int` :raise TypeError if the parameter is not valid and Exception if an error occurs. """ self._logger.info("Going to read from communication channel...") data = self.channel.read(timeout = timeout) self._logger.info("Received : {}".format(repr(data))) symbol = None for potential in self.symbols: try: self.parser.parseMessage(RawMessage(data), potential) symbol = potential self.memory = self.parser.memory self.specializer.memory = self.memory break except Exception, e: symbol = None
def readSymbol(self, timeout=EmptySymbol.defaultReceptionTimeout()): """Read from the abstraction layer a message and abstract it into a message. The timeout parameter represents the amount of time (in millisecond) above which no reception of a message triggers the reception of an :class:`netzob.Common.Models.Vocabulary.EmptySymbol.EmptySymbol`. If timeout set to None or to a negative value means it always wait for the reception of a message. :keyword timeout: the time above which no reception of message triggers the reception of an :class:`netzob.Common.Models.Vocabulary.EmptySymbol.EmptySymbol` :type timeout: :class:`int` :raise TypeError if the parameter is not valid and Exception if an error occurs. """ self._logger.info("Going to read from communication channel...") data = self.channel.read() self._logger.info("Received data: '{0}'".format(repr(data))) symbol = AbstractField.abstract(data, self.symbols) if symbol is not None: self._logger.info("Received symbol on communication channel: '{0}'".format(symbol.name)) else: self._logger.info("Received symbol on communication channel: '{0}'".format(symbol)) return (symbol, data)
def findCounterExample(self, mmstd, inputSymbols, cache): self.log.info("=====================================================") self.log.info("Find a counterexample which invalids the given MMSTD") self.log.info("=====================================================") inputDictionary = [] for entry in inputSymbols: letter = DictionarySymbol(entry) inputDictionary.append(letter) self.log.info("The vocabulary contains: {0}".format(str(letter))) # ----------------------------------------------------------------------- # FIRST WE COMPUTE WHICH WILL WE MAKE ! # ----------------------------------------------------------------------- # This our plan to find same # STEP 1 : Estimate the maximum number of states (m) in the correct implementation # of the FSM (DONE PREVISOULY AND TRANSMITED THROUGH PARAM self.maxsize # STEP 2 : Construct the characterization set W for [MMSTD] # STEP 3: # (a) Construct the "testing tree" for MMSTD # (b) Generate the transition cover set P from the testing tree # STEP 4 : Construct set Z from W and m # STEP 5 : We have the list of so desired test cases = P.Z # STEP 2: # - Construct a sequence of k-equivalence partitions of the states of MMSTD: # Find all the couples of states couples = [] states = mmstd.getAllStates() W = [] self.log.info("The MMSTD has " + str(len(states)) + " states") self.log.info("A number of " + str(self.m) + " states is estimated.") for state in states: for state2 in states: if state != state2: found = False for (s1, s2) in couples: if not ((s1 == state) and (s2 == state2) or ((s1 == state2) and (s2 == state))): found = True if not found: couples.append((state, state2)) self.log.info("A number of " + str(len(couples)) + " couples was found") for (state1, state2) in couples: self.log.info("Search a distinguish string between " + state1.getName() + " and " + state2.getName()) z = MembershipQuery([EmptySymbol()]) mqToTest = deque([]) for letter in inputDictionary: mqToTest.append( z.getMQSuffixedWithMQ(MembershipQuery([letter]))) lastIndiguishableZ = z distinguishableZ = z done = False i = 0 while not done: mq = mqToTest.popleft() if i > self.m * self.m: break self.log.info("Can we distinguish with MQ = " + str(mq)) if not self.canWeDistinguishStates(mmstd, mq, state1, state2): done = False lastIndiguishableZ = mq for letter in inputDictionary: z = mq.getMQSuffixedWithMQ(MembershipQuery([letter])) mqToTest.append(z) else: done = True distinguishableZ = mq i = i + 1 self.log.info( "FOUND: the following distinguish them: {0} last which doesn't is {1}" .format(str(distinguishableZ), str(lastIndiguishableZ))) W.append(distinguishableZ) self.log.info("=================================") self.log.info("W = " + str(W)) self.log.info("=================================") # Execute STEP 3 : We compute P # init P = {E, ...} currentMQ = MembershipQuery([EmptySymbol()]) P = [currentMQ] openMQ = deque([currentMQ]) closeMQ = [] statesSeen = [mmstd.getInitialState()] while len(openMQ) > 0: self.log.info("Compute P, ...") mq = openMQ.popleft() tmpstatesSeen = [] for letter in inputDictionary: z = mq.getMQSuffixedWithMQ(MembershipQuery([letter])) self.log.debug( "Get output trace if we execute the MMSTD with " + str(z.getSymbols())) (trace, outputState) = mmstd.getOutputTrace(mmstd.getInitialState(), z.getSymbols()) if outputState in statesSeen: # we close this one self.log.info("Adding " + str(z) + " in closeMQ") closeMQ.append(z) else: tmpstatesSeen.append(outputState) self.log.info("Adding " + str(z) + " in closeMQ") closeMQ.append(z) # still open openMQ.append(z) statesSeen.extend(tmpstatesSeen) P.extend(closeMQ) # STEP 4 : We compute Z # it follows the formula Z= W U (X^1.W) U .... U (X^(m-1-n).W) U (W^(m-n).W) self.log.info("Computing Z:") Z = [] # First we append W in Z for w in W: Z.append(w) v = self.m - len(states) if v < 0: v = 0 mqInputs = [] for input in inputDictionary: mqInputs.append(MembershipQuery([input])) X = dict() X[0] = W for i in range(1, v + 1): self.log.info("Computing X^{0}: ".format(str(i))) self.log.info("MQ INputs: ".format(str(len(mqInputs)))) self.log.info("W: ".format(str(len(W)))) X[i] = [] previousX = X[i - 1] self.log.info(previousX) for x in previousX: X[i].extend(x.multiply(mqInputs)) for w in W: for xi in X[i]: if not xi in Z: Z.append(xi) else: self.log.warn( "Impossible to add X[{0}] = {1} in Z, it already exists" .format(str(i), str(xi))) for z in Z: self.log.info("z = {0}".format(str(z))) # STEP 5 : We have the list of so desired test cases T = P.Z T = [] for p in P: T.extend(p.multiply(Z)) self.log.info("Tests cases are: ") for t in T: self.log.info("=> {0}".format(str(t))) testsResults = dict() self.log.info( "----> Compute the responses to the the tests over our model and compare them with the real one" ) i_test = 0 # We compute the response to the different tests over our learning model and compare them with the real one for test in T: i_test = i_test + 1 # Compute our results (traceTest, stateTest) = mmstd.getOutputTrace(mmstd.getInitialState(), test.getSymbols()) # Verify the request is not in the cache cachedValue = cache.getCachedResult(test) if cachedValue is None: # Compute real results if self.resetScript != "": os.system("sh " + self.resetScript) self.log.debug("=====================") self.log.debug("Execute test {0}/{1}: {2}".format( str(i_test), str(len(T)), str(test))) self.log.debug("=====================") isMaster = not self.communicationChannel.isServer() testedMmstd = test.toMMSTD(mmstd.getVocabulary(), isMaster) # TODO TODO oracle = NetworkOracle(self.communicationChannel, isMaster) # TODO TODO is master ?? oracle.setMMSTD(testedMmstd) oracle.start() while oracle.isAlive(): time.sleep(0.01) oracle.stop() if isMaster: resultQuery = oracle.getGeneratedOutputSymbols() else: resultQuery = oracle.getGeneratedInputSymbols() cache.cacheResult(test, resultQuery) else: resultQuery = cachedValue mqOur = MembershipQuery(traceTest) mqTheir = MembershipQuery(resultQuery) if not mqOur.isStrictlyEqual(mqTheir): self.log.info("========================") self.log.info("We found a counter example") self.log.info("========================") self.log.info("TEST: {0}".format(str(test))) self.log.info("OUR: {0}".format(str(mqOur))) self.log.info("THEIR: {0}".format(str(mqTheir))) return test else: self.log.info("========================") self.log.info("Not a counter example") self.log.info("========================") return None
class AbstractionLayer(object): """An abstraction layer specializes a symbol into a message before emitting it and on the other way, abstracts a received message into a symbol. >>> from netzob.all import * >>> symbol = Symbol([Field("Hello Zoby !")], name = "Symbol_Hello") >>> channelIn = UDPServer(localIP="127.0.0.1", localPort=8889) >>> abstractionLayerIn = AbstractionLayer(channelIn, [symbol]) >>> abstractionLayerIn.openChannel() >>> channelOut = UDPClient(remoteIP="127.0.0.1", remotePort=8889) >>> abstractionLayerOut = AbstractionLayer(channelOut, [symbol]) >>> abstractionLayerOut.openChannel() >>> abstractionLayerOut.writeSymbol(symbol) >>> (receivedSymbol, receivedMessage) = abstractionLayerIn.readSymbol() >>> print receivedSymbol.name Symbol_Hello >>> print receivedMessage Hello Zoby ! """ def __init__(self, channel, symbols): self.channel = channel self.symbols = symbols self.memory = Memory() self.specializer = MessageSpecializer(memory = self.memory) self.parser = MessageParser(memory = self.memory) @typeCheck(Symbol) def writeSymbol(self, symbol): """Write the specified symbol on the communication channel after specializing it into a contextualized message. :param symbol: the symbol to write on the channel :type symbol: :class:`netzob.Common.Models.Vocabulary.Symbol.Symbol` :raise TypeError if parameter is not valid and Exception if an exception occurs. """ if symbol is None: raise TypeError("The symbol to write on the channel cannot be None") self._logger.info("Going to specialize symbol: '{0}' (id={1}).".format(symbol.name, symbol.id)) dataBin = self.specializer.specializeSymbol(symbol).generatedContent self.memory = self.specializer.memory self.parser.memory = self.memory data = TypeConverter.convert(dataBin, BitArray, Raw) symbol.messages.append(RawMessage(data)) self._logger.info("Data generated from symbol '{0}':\n{1}.".format(symbol.name, symbol)) self._logger.info("Going to write to communication channel...") self.channel.write(data) self._logger.info("Writing to commnunication channel donne..") @typeCheck(int) def readSymbol(self, timeout=EmptySymbol.defaultReceptionTimeout()): """Read from the abstraction layer a message and abstract it into a message. The timeout parameter represents the amount of time (in millisecond) above which no reception of a message triggers the reception of an :class:`netzob.Common.Models.Vocabulary.EmptySymbol.EmptySymbol`. If timeout set to None or to a negative value means it always wait for the reception of a message. :keyword timeout: the time above which no reception of message triggers the reception of an :class:`netzob.Common.Models.Vocabulary.EmptySymbol.EmptySymbol` :type timeout: :class:`int` :raise TypeError if the parameter is not valid and Exception if an error occurs. """ self._logger.info("Going to read from communication channel...") data = self.channel.read(timeout = timeout) self._logger.info("Received : {}".format(repr(data))) symbol = None for potential in self.symbols: try: self.parser.parseMessage(RawMessage(data), potential) symbol = potential self.memory = self.parser.memory self.specializer.memory = self.memory break except Exception, e: symbol = None if symbol is None and len(data) > 0: symbol = UnknownSymbol() elif symbol is None and len(data) == 0: symbol = EmptySymbol() symbol.messages.append(RawMessage(data)) self._logger.info("Received a message abstracted with symbol '{}' on communication channel:\n{}".format(symbol.name, symbol)) return (symbol, data)