Beispiel #1
0
    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)
Beispiel #3
0
    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
Beispiel #4
0
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)