We’re going to build some ransomware. This document covers the high level design and a few details to get us started. We’ll be using an asymmetric + symmetric encryption scheme for locking files. We’ll also build a server for handling decryption. All of this will be written in Go, so it will be cross platform. Our malware will show off Go’s great parallelization and networking capabilities. From there we’ll get into the technical details and start looking at anti-analysis tricks and signature writing. I’ll take you through everything step by step.
Design
Encryptor
The encryptor is the malware sample that gets dropped on the victim’s computer. It will use a common asymmetric + symmetric encryption scheme for encrypting files. It will walk directories, visiting each file. It will selectively target certain files based on mimetype, extension, or size. Encryption Scheme
The server will have an asymmetric keypair (e.g. RSA). The server private key will be kept private on the server. The server public key will be embedded in the encryptor client. When the client runs it will generate a client keypair and encrypt the private key with the server’s public key. For each file, it will generate a random symmetric key (e.g. AES). That file key will be used to encrypt the file contents, then that key will be encrypted with the client’s public key and stored. We will also store the IV and number of padding bytes for each file.
type EncryptionInfo struct { Path string Padding uint8 Key []byte Iv []byte }
This allows the server to unlock a machine by decrypting the single client private key. That client key and be used to decrypt each file key, and each file key, in turn, can be used to decrypt its respective file.
File Walking
This will be incredibly simple. The Go package path/filepath includes a method Walk. We’ll implement the visitor function to handle each file. This is where we can add filtering to not target files that are too large or an unknown file type. For detecting file types we will either use mimetype or http.DetectContentType. Server
The server will be a standard HTTP server in Golang. These are super easy to write. We’ll look at HTML templating for the front-end portion of the site. This will have a few support methods for the client.
While the client won’t always have a network connection, when it does we will upload the encrypted key to the server to save the user from having to. For this we’ll have some endpoint like /storeKey. The front-end will need an endpoint to trigger decryption, something like /decrypt, where it can post the user’s key file (or the simple code in place of the file) and get back the decryptor.
Milestones
Environment
This is where we will get set up. Right now I think it will just be installing Go, which is incredibly straight forward. You will also learn about the project layout and any other information that will be helpful pre-code.
Victim directory setup
I’ll be working on the computer I use daily as I’m sure many of you will too. Since we do not want to be encrypting our disks before we have written a decryptor, we’ll write a program to set up a victim directory. If the directory currently exists it will remove it, then it will copy in a directory structure we have established elsewhere on disk. We’ll be running our encryptor repeatedly while debugging it, this will allow an easy set up and tear down of the test directory.
Key generator
Following the standard ransomware encryption scheme, we’ll need a master key pair for the server to use. We’ll dive more into encryption later, but the short of it is we will be using AES (symmetric) to encrypt the files, we’ll encrypt those keys with an asymmetric client keypair. The private key of the client keypair will be encrypted by the server keypair’s public key. In this milestone we will write a program that generates the server keypair, saves it to disk, and prints out the public key in a code-friendly format for our encryptor client.
Encryptor
We finally get to write our ransomware client! Here we’ll start with building blocks of the client, such as asymmetric and symmetric cryptography and walking a directory structure. Then we will combine these pieces into a simple but functional prototype that will get refined throughout the rest of the series.
Server and key decryption
The encryptor needs a server that takes payment (ours won’t, see: Not Covered) and returns a decrypted client key. Here we’ll learn about writing web servers in Go and HTML templating. Rather than running a separate application like Apache, we can get a webserver up and running with just Go code. We will then expand on this for better usability. For example, most users will not have the technical skills to find and upload the key file, so our encryptor client should do it for them when it has network connectivity.
File decryption
Since you have the encryptor written, this should be fairly straight forward. We just need to flip the encryption methods to be decryption methods using the same directory walking. Once this is done you’ll have an end-to-end functional prototype. Another usability improvement will be to patch the decrypted key into a pre-built decryptor. This way the user does not need to manage two separate files.
Anti-analysis
A lot of anti-analysis techniques are OS specific. Since we are building cross-platform malware there is a limit to what can be implemented. What is possible is process enumeration. Malware tends to check for known analysis programs (debuggers, network capturing tools, etc.) and can either decide to kill them, not run, or do something else entirely. We’ll explore a few of these options.
Another anti-analysis option we have in Go is to do timing checks. If the process is being stepped through in a debugger, the execution will be much slower than it normally would. We can capture a start time then an end time at some other point and check that the difference is within some threshold of our normal measurement.
Parsing debug information
Next we will take an analysis point of view and see how much information we can recover form our Go binary. We will explore the debug information and the executable file format (either ELF or PE) by reimplementing the work done in this awesome blog post. We’ll also explore ways to ruin these helpful debug hints.
Signature coverage
In this milestone we will take a defensive posture by writing ClamAV and YARA signatures for our ransomware. We will start by looking at hash based signatures and see why they suck. Next we’ll move onto real signature writing strategies, getting byte based coverage.
Not Covered (yet)
Accepting payments
Payments aren’t covered for 2 reasons. The first being I don’t want to provide some ready-to-go malware package for people to ruin their lives with. The other is that it is actually a pretty large topic that I’ll cover in the future when we set up a darknet e-commerce shop.
OS specific techniques
A lot of anti-analysis techniques are OS specific. We won’t be covering those here. We’ll work on some OS specific implants at a way later date. Right now we’re going to skip manually loading our libraries and injecting into other processes. This allows our malware to be cross platform, which is great since 2020 is the year of the Linux desktop.
Opsec
Opsec is antithetical to operational efficiency. We’d spend much more time on protecting our anonymity than writing this ransomware. We don’t need to spend $50 dollars on a burner, worry about buying our hosting services with untraceable Bitcoin, or figure out how to bootstrap an email account over Tor so you can purchase a VPN. I’ve written about some orthogonal topics it in the past and it’s not easy.
Infection
My dad got infected with Sigma ransomware from a response to his Craigslist casual encounters post (jk, it was a job ad). Word documents with macros are a common infection vector. In the same spirit of not providing a fully weaponized system, that will not be covered in this series.
Conclusion
This should be really fun. I’ve had fun prototyping it and you’ll have a blast and learn a lot running through it. I also have a ton of great topics planned once we’re done.