コード例 #1
0
	def test_pattern_guesser( self ) :

		config = '''
X:_data_:
Y:_data_:

data1="""41414141XXYY"""
data2="""41414142XXYY"""
'''
		psi = StegoInjector( config )

		pkt1 = 'AAAAcd'
		pkt2 = 'AAAdfg'

		res, score = psi.guessTemplate( pkt1 )
		# print( res )

		self.assertTrue( res == 'data1' )
コード例 #2
0
class DataTransformer:
    """
This class provides automated data transformations.
It uses the :class:`covertutils.datamanipulation.stegoinjector.StegoInjector` class to create alterations to existing data chunks.

**Transformation List**

The Transformation List argument is a specially structured list to dictate to the `DataTranformer` which changes should be done to data packet.
Specifically, for a SYN - (RST, ACK) sequence to be simulated, the following configuration should be used:

.. code:: python

	X:_data_:
	L:_data_:
	K:_data_:

	ip_tcp_syn = '''45000028LLLL000040067ccd7f0000017f000001XXXX0050KKKKKKKK0000000050022000917c0000'''

	ip_tcp_rst_ack = '''450000280001000040067ccd7f0000017f0000010014005000000000XXXXXXXXXX50142000916a0000'''

The Transformation List that has to be used should dictate the class to:

 - Unpack Sequence Number from `ip_tcp_syn` template (K tag)
 - Increment it by 1
 - Place it to a `ip_tcp_rst_ack` template (X tag)
 - All the above while handling **endianess**, **integer overflow checks**, etc

The `transformation_list` is declared below:

.. code:: python

	transformation_list = [ (	# Tranformation #1
		( 'ip_tcp_syn:K', 'ip_tcp_rst_ack:X' ),		# From template:tag to template:tag
		('!I','!I')		# Unpack as an 4-byte Integer (reverse Endianess as of network Endianess) and pack it to 4-byte Integer (reverse Endianess again)
		'_data_ + 1'	# Eval this string (with the extracted/unpacked data as '_data_') and pack the result.
		),
			# No other transformations
	]

"""
    def __init__(self, stego_configuration, transformation_list):
        """
:param str stego_configuration: The Stego Configuration to initialize the internal :class:`covertutils.datamanipulation.stegoinjector.StegoInjector` object.
:param list transformation_list: The Tranformation List as described above.

		"""
        self.injector = StegoInjector(stego_configuration)
        self.transformation_list = transformation_list

    def runAll(self, pkt, template=None):
        """
Runs all Tranformations in the `transformation_list` that relate to the specified template.

:param str pkt: The data packet to run the Tranformations on. In `Raw Bytes`.
:param str template: The template string that describes the given data packet. If `None` the :func:`covertutils.datamanipulation.stegoinjector.StegoInjector.guessTemplate` function will try to guess the correct template.
:rtype: str
:return: Returns the `pkt` with all the related tranformations applied.
		"""
        if not template:
            template = self.injector.guessTemplate(pkt)

        for trans_tuple in self.transformation_list:

            templates, struct_strs, eval_str = trans_tuple
            (out_template_tag, in_template_tag) = templates
            out_template, out_tag = out_template_tag.split(':')
            in_template, in_tag = in_template_tag.split(':')
            (out_struct, in_struct) = struct_strs

            # if template != out_template :
            # 	continue

            out_data = self.injector.extractByTag(pkt, template)[out_tag]
            structed_data = unpack(out_struct, out_data)[0]
            #		==========================
            _data_ = structed_data
            output_data = eval(eval_str)
            # print( structed_data, eval_str, output_data )
            #		==========================
            injectable_data = pack(in_struct, output_data)
            # injectable_dict = {'X' : injectable_data }
            # print( injectable_data.encode('hex') )
            # print( self.injector.getCapacity( template ), len( injectable_data) )
            # pkt = self.injector.injectByTag( injectable_dict, template, pkt  )
            pkt = self.injector.inject(injectable_data, template, pkt)

        return pkt
コード例 #3
0
ファイル: stegoorchestrator.py プロジェクト: how2how/ToyHome
class StegoOrchestrator(Orchestrator):
    """
The `StegoOrchestrator` class combines compression, chunking, encryption, stream tagging and steganography injection, by utilizing the below ``covertutils`` classes:

 - :class:`covertutils.datamanipulation.AdHocChunker`
 - :class:`covertutils.datamanipulation.Compressor`
 - :class:`covertutils.crypto.keys.StandardCyclingKey`
 - :class:`covertutils.orchestration.StreamIdentifier`
 - :class:`covertutils.datamanipulation.StegoInjector`
 - :class:`covertutils.datamanipulation.DataTransformer`


The `StegoOrchestrator` packs `(stream, message)` pairs in predefined data templates.
	"""
    def __init__(self,
                 passphrase,
                 stego_config,
                 main_template,
                 transformation_list=[],
                 tag_length=2,
                 cycling_algorithm=None,
                 streams=[],
                 hex_inject=False,
                 reverse=False):
        """
:param str stego_config: The configuration that is passed to :class:`covertutils.datamanipulation.stegoinjector.StegoInjector`.
:param str main_template: The default template that will be used in :func:`readyMessage()` `template` argument.
:param list transformation_list: The Transformation List that is passed to the :class:`covertutils.datamanipulation.datatransformer.DataTransformer` object.
:param class cycling_algorithm: The hashing/cycling function used in all OTP crypto and stream identification. If not specified the  :class:`covertutils.crypto.algorithms.StandardCyclingAlgorithm` will be used. The :class:`hashlib.sha256` is a great choice if `hashlib` is available.
:param list streams: The list of all streams needed to be recognised by the `SimpleOrchestrator`. A "control" stream is always hardcoded in a `SimpleOrchestrator` object.
:param func intermediate_function: A *codec* function with signature `codec( data, encode = False )`. The function is called before and injection of a chunk with *encode = True* and after the extraction of a chunk with *encode = False*.
:param bool reverse: If this is set to `True` a `StegoOrchestrator` with reverse streams is created. This parameter is typically used to keep the parameter list the same between 2 `StegoOrchestrator` initializations, yet make them `compatible`.
		"""

        self.stego_injector = StegoInjector(stego_config, hex_inject)
        self.data_tranformer = DataTransformer(stego_config,
                                               transformation_list)

        self.cycling_algorithm = cycling_algorithm
        if self.cycling_algorithm == None:
            self.cycling_algorithm = StandardCyclingAlgorithm

        self.main_template = main_template
        self.current_template = main_template

        self.chunk_sizes = {}

        super(StegoOrchestrator,
              self).__init__(passphrase,
                             tag_length=tag_length,
                             cycling_algorithm=cycling_algorithm,
                             streams=streams,
                             history=1,
                             reverse=reverse)

        for index, template in enumerate(self.stego_injector.getTemplates()):
            stego_capacity = self.stego_injector.getCapacity(template)
            # 	# print stego_capacity
            # 	# inter_product = self.intermediate_function( "0" * stego_capacity, False )	# Need a valid decodable data string "0000..." is valid hex, base64, etc
            # intermediate_cap = stego_capacity - self.tag_length 		# check the capacity of the data length after the intermediate function
            #
            intermediate_cap = stego_capacity  # check the capacity of the data length after the intermediate function
            # 	# intermediate_cap = len( inter_product )	 		# check the capacity of the data length after the intermediate function
            #
            self.chunk_sizes[template] = intermediate_cap

    @copydoc(Orchestrator.readyMessage)
    def readyMessage(self, message, stream=None):

        template = self.current_template
        if stream == None:
            stream = self.default_stream

        # template_capacity = self.stego_injector.getCapacity( template )
        template_capacity = self.chunk_sizes[template]
        # print "Lengths: template_length = %d" % template_capacity
        self.streams_buckets[stream]['chunker'].setChunkSize(template_capacity)
        chunks = super(StegoOrchestrator, self).readyMessage(message, stream)
        # print "Lengths: chunk_length = %d" % len(chunks[0])

        ready_chunks = []
        for chunk in chunks:

            modified_chunk = chunk
            # modified_chunk = self.intermediate_function( chunk, True )
            # print "<--"
            # print chunk.encode('hex')
            # print modified_chunk.encode('hex')
            injected = self.stego_injector.inject(modified_chunk, template)

            alterations = self.__getAlterations(
                template)  # needs to be documented

            transformed = injected
            for alteration_templ in alterations:
                transformed = self.data_tranformer.runAll(
                    transformed, alteration_templ)

            ready_chunks.append(transformed)
        return ready_chunks

    @copydoc(Orchestrator.depositChunk)
    def depositChunk(self, chunk):
        templ = self.stego_injector.guessTemplate(chunk)
        if templ == None:
            return (
                None, None
            )  # Trigger the notRecognised() method of the underlying Handler
        self.received_template = templ[0]
        extr_data = self.stego_injector.extract(chunk, self.received_template)

        ret = super(StegoOrchestrator, self).depositChunk(extr_data)
        return ret

    @copydoc(Orchestrator.addStream)
    def addStream(self, stream):
        super(StegoOrchestrator, self).addStream(stream)
        self.streams_buckets[stream]['chunker'] = AdHocChunker()

    def useTemplate(self, template):
        """
:param str template: The template to use for the next Message. Use `None` for random templates.
		"""
        self.current_template = template

    def lastReceivedTemplate(self):
        """
:rtype: str
:return: Returns the last template received.
		"""
        return self.received_template

    def __getAlterations(self, template):  # Document the '_alt' suffix
        templates = self.stego_injector.getTemplates()
        ret = []
        for templ in templates:
            if templ.startswith(template + "_alt"):
                ret.append(templ)
        return ret