Tomb/extras/cloak/decloakify.py

85 lines
3.5 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
#
# Filename: decloakify.py
#
# Author: Joe Gervais (TryCatchHCF)
#
# Summary: Exfiltration toolset (see cloakify.py) that transforms data into lists
# of words / phrases / Unicode to ease exfiltration of data across monitored networks,
# essentially hiding the data in plain sight, and facilitate social engineering attacks
# against human analysts and their workflows. Bonus Feature: Defeats signature-based
# malware detection tools (cloak your other tools).
#
# Used by cloakifyFactory.py, can be used as a standalone script as well (example below).
#
# Description: Decodes the output of cloakify.py into its underlying Base64 format,
# then does Base64 decoding to unpack the cloaked payload file. Requires the use of the
# same cipher that was used to cloak the file prior to exfitration, of course.
#
# Prepackaged ciphers include: lists of desserts in English, Arabic, Thai, Russian,
# Hindi, Chinese, Persian, and Muppet (Swedish Chef); Top 100 IP Addresses; GeoCoords of
# World Capitols; MD5 Password Hashes; An Emoji cipher; Star Trek characters; Geocaching
# Locations; Amphibians (Scientific Names); and evadeAV cipher, a simple cipher that
# minimizes the size of the resulting obfuscated data.
#
# Example:
#
# $ ./decloakify.py cloakedPayload.txt ciphers/desserts.ciph
import argparse
import base64
import random
import sys
array64 = list("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/+=")
def Decloakify(cloakedPath:str, cipherPath:str, outputPath:str="", password:str=""):
"""Cipher file will be read into a list that will be used for the payload's deobfuscation.
Cloaked file's contents will be read in line by line mapping the line to a base64 character.
If an output path is defined the base64 contents will be decoded and written to the output
file otherwise it will be written to the console.
Args:
cloakedPath (str): Path to the file that is encoded
cipherPath (str): Path to the file used as the base64 cipher
outputPath (str): Path to write out the decoded
"""
with open(cipherPath, encoding="utf-8") as file:
arrayCipher = file.readlines()
clear64 = ""
with open(cloakedPath, encoding="utf-8") as file:
if password:
random.seed(password)
lines = file.readlines()
# Get a list of each line number in the cloaked file
decodeOrdering = [i for i in range(len(lines))]
# Shuffle the order of the lines to what they were during encoding
random.shuffle(decodeOrdering)
# Map the index of the original payload to the index in the cloaked file
decodeOrdering = {k: v for v, k in enumerate(decodeOrdering)}
# Iterate through the proper line order and reconstruct the unshuffled base64 payload
for i in range(len(lines)):
clear64 += array64[arrayCipher.index(lines[decodeOrdering[i]])]
else:
for line in file:
clear64 += array64[arrayCipher.index(line)]
payload = base64.b64decode(clear64)
if outputPath:
with open(outputPath, "wb") as outFile:
outFile.write(payload)
else:
print(payload)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Transform file into unobfuscated text file.')
parser.add_argument('-i', "--input", type=str, help='Cloaked File Path', required=True)
parser.add_argument('-c', "--cipher", type=str, help='Cipher File Path', required=True)
parser.add_argument('-o', "--output", type=str, help='Output File Path', default="")
parser.add_argument('-p', "--password", type=str, help='Password', default=None)
args = parser.parse_args()
Decloakify(args.input, args.cipher, args.output, args.password)