def test_injection_from_dict_with_template(self, n=100):

        for i in range(2, n, 2):
            config = '''
	X:_data_:
	Y:_sxor_(_data_, '\xaa'):

	data1="""44444444%s41414141%s"""
			''' % ("X" * i, "Y" * i)

            inj_dict = {'X': 'a' * (i // 2), 'Y': 'b' * (i // 2)}

            psi = StegoInjector(config)

            templ_pkt = psi.inject('\x00' * i, 'data1')
            print templ_pkt, "<----"

            stego_pkt = psi.injectByTag(inj_dict,
                                        template='data1',
                                        pkt=templ_pkt)
            testable = 'DDDD%sAAAA%s' % ('a' * (i // 2), 'b' * (i // 2))

            # print( stego_pkt, testable )
            extr_dict = psi.extractByTag(stego_pkt, 'data1')
            # print( extr_dict, inj_dict )
            self.assertTrue(extr_dict == inj_dict)
示例#2
0
	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
示例#3
0
    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
示例#4
0
	def test_injection_from_text( self, n = 4) :
		config = '''
X:_data_:
Y:_data_:

data1="""44444444%s41414141%s"""
		''' % ("X"*n, "Y"*n)
		data = 'aabb'
		psi = StegoInjector( config )
		stego_pkt = psi.inject(data, template = 'data1')
		self.assertTrue( stego_pkt == 'DDDDaaAAAAbb')
示例#5
0
	def test_syntax( self ) :
		conf1 = "la:_data_:" # 2 letter tag
		try :
			p = StegoInjector( conf1 )
		except Exception as e :
			self.assertTrue ( type(e) == StegoSchemeParseException )

		conf2 = "C:_data_:" # Hex Letter
		try :
			p = StegoInjector( conf2 )
		except Exception as e :
			self.assertTrue ( type(e) == StegoSchemeParseException )
示例#6
0
	def test_injection_scramble( self, ) :
		config = '''
X:_data_:
Y:_data_:

data1="""44X44X4141Y4141Y44X43X"""
'''
		data = 'fff'	# 0x660x660x66
		psi = StegoInjector( config )
		stego_pkt = psi.inject(data, template = 'data1')

		self.assertTrue( stego_pkt.encode('hex').count('6') == 6 )
    def test_extraction_from_dict(self, n=4):
        config = '''
X:_data_:
Y:_data_:

data1="""44444444%s41414141%s"""
		''' % ("X" * n, "Y" * n)
        inj_dict = {'X': 'a' * (n // 2), 'Y': 'b' * (n // 2)}
        psi = StegoInjector(config)
        pkt = 'DDDDaaAAAAbb'
        extr_dict = psi.extractByTag(pkt, template='data1')

        self.assertTrue(inj_dict == extr_dict)
示例#8
0
	def test_injection_scramble2( self, ) :
		config = '''
X:_data_:
Y:_data_:

data1="""44X44X4141Y4141Y44X43X"""
'''
		pkt = codecs.decode('4464464141641416446436', 'hex')
		psi = StegoInjector( config )
		extr_pkt = psi.extract(pkt, template = 'data1')
		data = 'fff'

		self.assertTrue( extr_pkt == data  )
示例#9
0
	def test_syntax_multiple_packets( self ) :

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

data1="""44X44X4141Y4141Y44X43X"""

data2="""44X44X4141Y4141Y44X43X"""
'''
		psi = StegoInjector( config )
		cap1 = psi.getCapacity('data1')
		cap2 = psi.getCapacity('data2')
示例#10
0
	def test_injection_from_text_to_hex( self, n = 4) :
		config = '''
X:_data_:
Y:_data_:

data1="""44444444%s41414141%s"""
		''' % ("X"*n, "Y"*n)
		data = 'aa'
		psi = StegoInjector( config, hex_inject = True )
		stego_pkt = psi.inject(data, template = 'data1')

		extracted = psi.extract( stego_pkt, 'data1' )
		self.assertTrue( extracted == data )
示例#11
0
	def test_group_str_similarity( self ) :

		config = """
X:_data_:

data1 = '''4444444445454545'''X[2:6]
data2 = "4444XXXXXXXX4545"

		"""
		psi = StegoInjector( config )

		res1 = psi.inject("A"*4, 'data1')
		res2 = psi.inject("A"*4, 'data2')

		self.assertTrue( res1 == res2 )
示例#12
0
	def test_ascii_to_hex_template( self, n = 1000 ) :
		pkt = urandom( n )
		pkt = pkt.replace(pkt[-1], '~')
		pkt = pkt.replace(pkt[-2], '~')
		pkt = pkt.replace(pkt[-3], '~')

		templ = asciiToHexTemplate( pkt )

		config = '''
X:_data_:

data1="""%s"""
''' % templ
		psi = StegoInjector( config )
		cap = psi.getCapacity( 'data1' )
		inj = psi.inject(cap*'~', 'data1' )
		print( "Changed %d bytes" % cap )
		self.assertTrue( inj == pkt )
示例#13
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' )
示例#14
0
	def test_injection_with_pkt( self ) :
		config = '''
X:_data_:
Y:_data_:

data1="""44X44X4141Y4141Y44X43X"""

data2="""44X44X4141Y4141Y44X43X"""
'''
		psi = StegoInjector( config )

		pkt = "\xFF"*11

		inj_pkt = psi.inject( "\x00"*3, 'data1', pkt )

		# print( inj_pkt.encode('hex') )
		testable = "\xFF\x0F\xF0\xFF\xFF\x0F\xFF\xF0\xFF\x0F\xF0"
		# print( testable.encode('hex') )
		self.assertTrue( inj_pkt == testable)
示例#15
0
    def test_injection_from_dict(self, n=100):

        for i in range(2, n, 2):
            config = '''
	X:_data_:
	Y:_sxor_(_data_, '\xaa'):

	data1="""44444444%s41414141%s"""
			''' % ("X" * i, "Y" * i)

            inj_dict = {'X': 'a' * (i / 2), 'Y': 'b' * (i / 2)}

            psi = StegoInjector(config)
            stego_pkt = psi.injectByTag(inj_dict, template='data1')
            testable = 'DDDD%sAAAA%s' % ('a' * (i / 2), 'b' * (i / 2))

            # print stego_pkt, testable
            extr_dict = psi.extractByTag(stego_pkt, 'data1')
            # print extr_dict, inj_dict
            self.failUnless(extr_dict == inj_dict)
示例#16
0
	def test_injection_equivalence( self ) :
		config = '''
X:_data_:
Y:_sxor_(_data_, chr(_index_) ):

data1 = """XXXXYYYY"""
		'''
		psi = StegoInjector( config )
		data = "\x00"*4
		data_dict = { 'X' : "\x00" * 2, 'Y' : '\x00' * 2}

		pkt1 = psi.inject(data, 'data1')
		pkt2 = psi.injectByTag( data_dict, 'data1' )
		# print( pkt1.encode('hex'), pkt2.encode('hex') )
		self.assertTrue( pkt1 == pkt2 )
		extr1 = psi.extract( pkt1, 'data1' )
		extr_dict = psi.extractByTag( pkt2, 'data1' )
		self.assertTrue( data == extr1 )
		self.assertTrue( data_dict == extr_dict )
示例#17
0
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
示例#18
0
	),
	(       # Tranformation #4		-	Destination Port -> Source Port
        ( 'ip_tcp_syn:N', 'ip_tcp_rst_ack:M' ),
        ('!H','!H'),
        '_data_'
	),
	(       # Tranformation #5		-	SYN -> RST+ACK
        ( 'ip_tcp_syn:W', 'ip_tcp_rst_ack:W' ),
        ('!B','!B'),
        '_data_ + 18'	#	Make '02' (SYN) to '14' (RST+ACK)
	),
                # No other transformations
]

dt1 = DataTransformer(stego_config, transformation_list)
steg_inj = StegoInjector(stego_config)

orchestrator = SimpleOrchestrator( passphrase,
							tag_length = 3,
							in_length = 8,
							out_length = 6,
							)
packets = Queue.Queue()


def check_syn( pkt ) :
	pkt = pkt.encode('hex')
	tcp_flags = pkt[94:96]
	return tcp_flags == '02'

示例#19
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