No more _MEI folder with PyInstaller
If you prefer to code your Red Team tools in Python like I do and you use Pyinstaller to create a single executable of your code, then you may think that life is good. How nice is a simple one file executable that contains Python itself, your code, and all of the supporting third-party modules that your code relies on? It is almost as good as a statically compiled C program, well not quite that good, but you get the point. You can push your single EXE to any target system regardless of Python being on that system or not, and your code will run.
The problem is that it is a self extracting archive so to speak. When you run the program, it self extracts in to a temporary folder for the user or to a folder that you set with the –runtime-tmpdir option. It then creates a folder that begins with _MEI followed by a process id number. Then the Python Interpreter and all the byte code and packages are beneath that _MEI folder. Then it runs. Life is good. Well, life is good until the Incident Response team or Team Blue realizes that single executable files packaged by Pyinstaller are not normal on the network and they decide to create a signature that alerts every time a folder is created that begins with _MEI. 🙁
At this point, you could move to the “one folder” option with Pyinstaller instead of creating a “one file”, but that is messy because then you have to zip and unzip files. It is not as clean to use in social engineering/phishing attacks either. If you can code in other languages, you can always go that route. In my case, I know some C and C# but I have to admit, once learning Python and having access to so many amazing third party modules, it is hard to start a project with anything but Python. PowerShell is also a possibility but it seems to be heavy on the Incident Response radar, so I try to avoid it for anything serious.
The obvious answer is to change the _MEI to something else. I first tried to use a hex editor to find MEI in the one file executable and I was going to change it there, but that isn’t going to work. However, after some research I learned that you can compile the Pyinstaller bootloader yourself and if you can do that, then we should be able to
replace that _MEI in the code there and that is what I ended up doing and it worked like a charm! Team Blue keeps looking for _MEI folders being created but Team Red is using _JMP or whatever we prefer, just not MEI!
1. First, update your version of pyinstaller to the very latest. Do this within PyCharm or by using pip (pip install pyinstaller -U). I use PyCharm exclusively for my projects and only drop out to the command line and use pip if updating my system’s main Python packages.
Reference this page for help: https://pyinstaller.org/en/stable/bootloader-building.html
If you are on Windows, you will need to have a C++ compiler installed. I use Visual Studio on my system.
2. git clone https://github.com/pyinstaller/pyinstaller.git
I brought mine down to C:\Temp. I deleted it after a successful test.
3. You will need to move to the bootloader’s src folder (on my system: C:\Temp\pyinstaller\bootloader\src) and edit pyi_utils_posix.c and/or pyi_utils_win32.c. Change MEI to whatever you prefer. I chose JMP for this example. You can search for MEI in the file and quickly find the right location. Here is the location in the pyi_utils_win32.c file:

4. Using a command shell, cd to the pyinstaller/bootloader folder, up one level from the src directory. Then run the following command to compile the code:
python ./waf all
5. If successful, copy the run.exe, run_d.exe, runw.exe, and runw_d.exe files from the build subfolders (debug, debugw, release, and releasew).

6. Then go to your installed Pyinstaller’s bootloader folder and replace these run executable files with your new ones. You might want to back your old ones up first by creating a sub-folder and moving them in to it. I created a folder named orig.
On my system, I use PyCharm and all of my PyCharm projects are under C:\Projects\Python. After that is my project folder and then the virtual environment, which if you drill down, you will find the Pyinstaller bootloader folder. Place those copied files there.

7. Now you can build your program with the new Pyinstaller bootloader files in place.
8. You can define your Pyinstaller one-file builds as an external tool within PyCharm for each project. Here are the settings I use for my py_c2_get project:
Program: C:\Projects\Python\py_c2_get\.venv\Scripts\pyinstaller.exe
Arguments: -w –runtime-tmpdir “C:\Temp” -F win_client.py
Working directory: C:\Projects\Python\py_c2_get
9. After building, you can find your EXE file in the dist subfolder of your project. When you run the EXE that is generated, no more _MEI* folders!
And this one belongs to the Red Team! 🙂