So, one of my goofy goals for my little RRE series is to see just how many programming languages I can shove into one malware project. Thus far I have Python and HTML/CSS on the backend (yes I know HTML/CSS aren't programming languages, shut the hell up, nerd) and C/C++ on the victim malware. My next goal was to see if I could get Python running as a standalone executable and embed that executable in the malware. It doesn't necessarily add another language to the project, but it would teach me how to embed executables into my C malware, and I could probably figure out how to apply that to a ton of other languages.
Let's start with Py2Exe
Py2Exe is a library that allows you to take a Python file and bundle it into a semi-standalone or standalone executable. It has tons of legitimate uses, but it's also used in malware to allow malware authors to write powerful tooling in a much easier language than C/C++. For a while, it was probably less detected than the typical C-based executables, but now most EDR/XDR/DDR/BMR solutions can probably detect it as well.
I'll link you to the tutorial I followed to get started here, but it's fairly easy to get figured out. You basically create your main script with all of the functionality you want, and you create a compilation setup.py script that py2exe uses to configure and compile your executable.
A couple of notable things:
- You need to copy over all of the required libraries from your main python script to your setup script. This allows the setup script to know what to link together in the final executable.
- By default, py2exe doesn't create a truly standalone executable. I had to pass in some extra options to get it to bundle everything together. I'll show my code below so you don't have to bang your head against the keyboard for a couple hours trying to figure it out like I did.
- The end result is a pretty hectic /dist folder. You really should only need the one executable file, I think.
Here is the code for my setup script and embed.py
That will create the /dist folder as well as an embed.exe executable. You can test it out by just running the executable on its own to make sure it does what it should. I tested it against my API server and it worked as expected. Now let's link it with the rest of our malware!
The first idea
My initial idea was to generate the executable binary with Py2Exe and basically store the executable binary as a variable in my C/C++ code. This seemed simple... too simple. And it was. I got a ton of errors for trying to store a 35kb binary string as a variable. Apparently this is something you technically can do but it seemed like it was ungraceful enough to not do it.
So, I moved on to the next method, which ended up being the right one.
C/C++ allows you to embed resources through .rc files that essentially create a mapping between the executable and the resources via resource ID's. Basically you'll create a .rc file and a header file that creates a mapping between a file location corresponding to an asset, an asset type and a unique integer that serves as the resource ID.
If you look at the image below, you'll see the resource.h header file on the left and the Resource.rc file on the right. The RC file maps a variable-like macro to a file location corresponding to the resource we want to link. The header file then maps that macro to a unique identifier (101) that I can use in my code.
Let's take a look at the function that I wrote that will take the embedded resource and write it out to a file.
The hRsrc opens a handle to a resource by looking up the resource by its unique identifier, hardcoded in the call to the function MAKEINTRESOURCE(101). We then load that resource in with LoadResource(), find the size of the resource and load in the resource into a void pointer using SizeofResource() and LockResource(), respectively, and we can treat the buffer the same way we would any buffer. I chose to go ahead and write this out to a file that I could then execute trivially with CreateProcess(). I would think it would be better to go ahead and load this resource directly into memory and execute it from there, though, since you wouldn't be leaving behind a file artifact that way, but I really just wanted to make this work, honestly.
Now all you really have to do is call CreateProcess() with the location of the executable file that gets dumped out to a file and it will run your Python executable!
The coolest part about this setup is that it's fairly easy to mess with the Python code, recompile and re-embed it into my malware. Essentially, I make a change to the Python, re-compile it using Py2Exe, then re-compile my malware, and, since it is linked to the build location of my Python executable, it will automatically embed the newest version.
Next, I'm going to reverse this malware now that there is a wholly new embedded resource. There are tons of different places to look for detection and I think the embedded resource factor makes for an interesting reverse engineering subject. After that, we're going to play with some cool nuanced features, like writing the second stage to memory and making it a keylogger!