Internal Components¶
Here you can find code snippets from covertutils basic internal components.
They are documented under the covertutils
pages, but here they will parade in all their glory.
Their understanding is essential in case you want to create a new Orchestrator (covertutils.orchestration.orchestrator.Orchestrator
) class, or generally tinker with the internals.
The Cycling Algorithm¶
Docs @ covertutils.crypto.algorithms.standardcyclingalgorithm.StandardCyclingAlgorithm
>>> from covertutils.crypto.algorithms import StandardCyclingAlgorithm as calg
>>>
>>> calg("A") # Has the same API as the hashlib classes
<covertutils.crypto.algorithms.standardcyclingalgorithm.StandardCyclingAlgorithm object at 0x7f18034c44d0>
>>> calg("A").hexdigest()
'b1d841411463be057db1af5f41be284ebe6c144e9c2739415f93af7d7d5f417d'
>>> calg("A", length = 10).hexdigest()
'8d7d82938db18db15feb'
>>> calg("A", length = 10, cycles = 20).hexdigest()
'8d7d82938db18db15feb' # "cycles = 20" is the default argument value
>>> calg("A", length = 10, cycles = 21).hexdigest()
'b15ff5fa1b41c9273993'
>>> calg("B", length = 10, cycles = 21).hexdigest()
'6fc5096f819081719f9f'
>>>
Yet this algorithm is not a Secure Hasher, as it can contain collisions. It is only used for Cycling Key implementation
The Cycling Key¶
Docs @ covertutils.crypto.keys.standardcyclingkey.StandardCyclingKey
The Key cycles with every encryption/decryption making it impossible to decrypt the same ciphertext twice.
This makes it an efficient One-Time-Pad Scheme.
>>> from covertutils.crypto.keys import StandardCyclingKey as ckey
>>>
>>> key1 = ckey("SecretPassphrase")
>>> key2 = ckey("SecretPassphrase")
>>> message = "A"*100
>>>
>>> encr1 = key1.encrypt(message) # Encrypting the message with Key1
>>> print encr1.encode('hex')
00e8b5dd97ffff87324686f21ee1b5e10f4b1100b4442c1cccba76ec22ee003a840eb87b2974a421a6e31cec7b752f1d7bd1b8120220ed30236049a1c156fcde3ed02ecedf03a38902a61054ba5bdd016ac3fe01f13198b6565bab9bf11f0f0a2e122e7b
>>>
>>> print key2.decrypt(encr1)
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
>>>
>>> key1 = ckey("SecretPassphrase") # Resetting Key1 breaks sync with Key2
>>> encr1 = key1.encrypt(message)
>>> print key2.decrypt(encr1) # Key2 is ahead of Key1 as it has cycled in the previous decryption.
Y<]��;�E���~L��}:M��7���=%!��킿��lZi��ù�A{�A���U4� ?E��!!E��/��v1
K���/}�oe�|�8�
>>>
Stream Identification¶
Docs @ covertutils.orchestration.streamidentifier.StreamIdentifier
This class is the OTP provider for the whole package.
>>> from covertutils.orchestration import StreamIdentifier as StreamIdent
>>>
>>> streams = ['main','secondary','testing']
>>>
>>> id1 = StreamIdent("Pa55phra531", streams)
>>> id2 = StreamIdent("Pa55phra531", streams, reverse = True)
>>>
>>> tag = id1.getIdentifierForStream('main', byte_len=4)
>>> tag2 = id1.getIdentifierForStream('main', byte_len=4)
>>> tag3 = id1.getIdentifierForStream('testing', byte_len=4)
>>>
>>> tag4 = id1.getIdentifierForStream('secondary', byte_len=2)
>>>
>>> id2.checkIdentifier(tag)
'main'
>>> id2.checkIdentifier(tag2)
'main'
>>> id2.checkIdentifier(tag3)
'testing'
>>> id2.checkIdentifier(tag4)
'secondary'
>>>
>>> print (tag, tag2, tag3, tag4)
('`\xc9\xca\xeb', '\xe8\xf7$\x1f', '\x00\x03\xfa\xaf', 'v\x17')
>>>
>>> print (id2.checkIdentifier(tag))
None
Compressor¶
Docs @ covertutils.datamanipulation.compressor.Compressor
This class ensures that the data traveling through the wire are as minimal as possible. It does that by measuring the output of several compression algorithms.
Decompression works through trial & error.
>>> from covertutils.datamanipulation import Compressor
>>> from os import urandom
>>>
>>> rand_data = urandom(32)
>>> plain_data = "AB"*16
>>> print rand_data
w!�w`:Ƀ�tU��Jr���?ב�K��lݽ�
>>> print plain_data
ABABABABABABABABABABABABABABABAB
>>>
>>> comp = Compressor()
>>>
>>> comp_rand_data = comp.compress(rand_data) # Compressing random data is infeasible
>>> print comp_rand_data
w!�w`:Ƀ�tU��Jr���?ב�K��lݽ�
>>> print comp_rand_data == rand_data # So the returned bytearray is the initial data
True
>>> comp_plain_data = comp.compress(plain_data) # Compressing repeated text
>>> print comp_plain_data # Is really efficient though!
x�str�
�1
>>> print comp_plain_data == plain_data # So the best compression is returned
False
>>>
>>> print comp.decompress( comp_rand_data ) # The decompression tries all compression schemes
w!�w`:Ƀ�tU��Jr���?ב�K��lݽ�
>>> print comp.decompress( comp_rand_data ) == comp_rand_data
True # And return the initial data if all of them fail
>>> print comp.decompress( comp_plain_data ) == comp_plain_data
False
>>> print comp.decompress( comp_plain_data ) == plain_data # But if the data is truly compressed
True # It returns the decompressed form
>>>
Chunker¶
Docs @ covertutils.datamanipulation.chunker.Chunker
>>> from covertutils.datamanipulation import Chunker
>>>
>>> ch1 = Chunker( 10, 5 )
>>> ch2 = Chunker( 10, 5, reverse = True )
>>>
>>> message = "A"*100
>>>
>>> ch1.chunkMessage( message ) # 10 bytes each chunk, with delimiter.
['\x00AAAAAAAAA', '\x00AAAAAAAAA', '\x00AAAAAAAAA', '\x00AAAAAAAAA', '\x00AAAAAAAAA', '\x00AAAAAAAAA', '\x00AAAAAAAAA', '\x00AAAAAAAAA', '\x00AAAAAAAAA', '\x00AAAAAAAAA', '\x00AAAAAAAAA', '\x01A\xe8\xfce\xe2\r\xd6\xb9t']
>>> # The last chunk contains random padding
>>>
>>> chunks = ch1.chunkMessage( message )
>>> print chunks
['\x00AAAAAAAAA', '\x00AAAAAAAAA', '\x00AAAAAAAAA', '\x00AAAAAAAAA', '\x00AAAAAAAAA', '\x00AAAAAAAAA', '\x00AAAAAAAAA', '\x00AAAAAAAAA', '\x00AAAAAAAAA', '\x00AAAAAAAAA', '\x00AAAAAAAAA', '\x01A\xa8\x8e\xa2\xf7v"\xb6/']
>>>
>>> for chunk in chunks :
... ch2.deChunkMessage( chunk )
...
(None, None)
(None, None)
(None, None)
(None, None)
(None, None)
(None, None)
(None, None)
(None, None)
(None, None)
(None, None)
(None, None)
(True, 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')
>>>
Steganography Injector¶
Docs @ covertutils.datamanipulation.stegoinjector.StegoInjector
The most engineered class in the whole project.
>>> from covertutils.datamanipulation import StegoInjector
>>>
>>> stego_config = '''
... X:_data_:
... Y:_sxor_( chr(_index_), _data_ ):
...
... sample1="""4142XXYYXXYY4344"""
... '''
>>>
>>> sinj = StegoInjector(stego_config)
>>>
>>> payload = sinj.inject("\x00" * 4, 'sample1')
>>> print payload.encode('hex')
4142000300054344
>>>
>>> payload2 = sinj.injectByTag( {'X' : '\xff' * 2, 'Y' : '\x00' * 2}, 'sample1')
>>> print payload2.encode('hex')
4142ff03ff054344
>>>
>>> sinj.extract(payload, 'sample1')
'\x00\x00\x00\x00'
>>>
>>> sinj.extractByTag(payload2, 'sample1')
{'Y': bytearray(b'\x00\x00'), 'X': bytearray(b'\xff\xff')}
>>>
>>> sinj.guessTemplate(payload)
('sample1', 1.0) # (template_name, possibility)
>>>
Steganography Packet Templating¶
HTTP Protocol Stego¶
>>> from covertutils.datamanipulation import asciiToHexTemplate
>>>
>>> search_request="""GET /search.php?q=~~~~~~~~?userid=~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ HTTP/1.1
... Host: {0}
... Cookie: SESSIOID=~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
... eTag: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
... """
>>> search_template = asciiToHexTemplate(search_request)
>>>
>>> print search_template
0a474554202f7365617263682e7068703f713dXXXXXXXXXXXXXXXX3f7573657269643dXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX20485454502f312e310a486f73743a207b307d0a436f6f6b69653a2053455353494f49443dXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX0a655461673a20XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX0a0a
>>>
>>> stego_config = """
... X:_data_:
... search='''%s'''
... """ % search_template
>>>
>>> from covertutils.datamanipulation import StegoInjector
>>>
>>> sinj = StegoInjector(stego_config)
>>> sinj.getCapacityDict( 'search' )
{'X': 212}
>>>
>>> packet = sinj.inject("A"*212, 'search')
>>> print packet
GET /search.php?q=AAAAAAAA?userid=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA HTTP/1.1
Host: {0}
Cookie: SESSIOID=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
eTag: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
>>>