Want to get cool research straight to your inbox every week? Join the Valhalla Weekly Newsletter here!
One of the bigger reasons I wanted to get into writing malware is because my work writing API's using Flask lead me to think it would be fairly fun to write a malware Command-and-Control using that very same library. It's extensible, modular and you can write a front-end command interface fairly easily. So, this is the first of many blogs on writing malware C2's using Python Flask.
We'll talk a bit about the design of the system first before we hop right into the implementation, but I'll leave the code for the C2 below if you want to copy/paste it or follow along in the code while you read the blog.
The basic design structure is this:
For right now, I'm going to stick with a flat text file structure that I might eventually replace with a database. The malware will reach out to an API endpoint to receive commands. The API endpoint will look in the text file corresponding to the victim that is reaching out and check to see if there are any commands present. If they are, it will respond to the malware's request with the command. Then, after the command is run on the victim system, the malware will send the results or any output from the command back to the C2 via a separate API endpoint, where it will be logged in the text file.
The dashboard will have the capability to actually create the commands in the text files via a simple (read: ugly) front end. After the command is issued and written to the text file, it will create a link that will hit another API endpoint that will check the text file for a response. If there is no response, it will echo that as a still-waiting status. If there is a response, it will be echoed on the front-end of the page.
This design pretty well decouples the victim from the C2 and is fairly hardened against errors, so I'm fairly confident in the design choices thus far. It's also agnostic to what commands are actually run, the C2 just passes the command to the victim and the output to the dashboard, so it will extend well as I add new functionality.
So, looking at the code above, we can see all of the basic backend functionality is there:
- get_cmd() - This function allows a victim to get the command stored in its corresponding JSON file. The function itself just loads the file in as a JSON dictionary, attempts to parse it out and sends the resulting command if its present in the file and sends a notification that a command wasn't found if it hits a parsing error
- get_res() - This function takes a host and an ID as input in a GET request and checks the corresponding host file. The host file should have a sub-dictionary of id:command result mappings, so it looks up the result by the ID of the command, which will be passed to the victim when the command is created.
- create_cmd() - This function creates a command and resides at an API endpoint that will be hit by the malware operator via front-end or API. The ID mentioned above is created by concatenating the hash of the command with the timestamp which should prevent duplicate ID's. The command is written to the corresponding text file along with the ID to be fetched later by the victim. This ID will then be used to store and fetch the result later.
- create_res() - This is the API endpoint that will be hit by the victim to write a result to the host file. The structure of the result data is just a mapping between the command ID and the result of the command that's run.
This implementation is fairly crude, but I think it will work. The only reason why I say "I think" is that I've yet to implement the victim-side code to test it out entirely. So this is definitely still a big work in progress. I also need to implement the front-end for the user to be able to issue commands from the web interface, so like I said, we're still very much incomplete here.