{"id":599,"date":"2025-02-27T20:27:59","date_gmt":"2025-02-28T01:27:59","guid":{"rendered":"https:\/\/offensivepython.com\/?p=599"},"modified":"2025-02-27T20:53:54","modified_gmt":"2025-02-28T01:53:54","slug":"no-more-mei-folder-with-pyinstaller","status":"publish","type":"post","link":"https:\/\/offensivepython.com\/index.php\/2025\/02\/27\/no-more-mei-folder-with-pyinstaller\/","title":{"rendered":"No more _MEI folder with PyInstaller"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"599\" class=\"elementor elementor-599\">\n\t\t\t\t<div class=\"elementor-element elementor-element-3b529cff e-flex e-con-boxed e-con e-parent\" data-id=\"3b529cff\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-2b4ef1e0 elementor-widget elementor-widget-text-editor\" data-id=\"2b4ef1e0\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>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\u00a0think that life is good.\u00a0 How nice is a simple one file executable that\u00a0contains Python itself, your code, and all of the supporting third-party\u00a0modules that your code relies on?\u00a0 It is almost as good as a statically\u00a0compiled C program, well not quite that good, but you get the point.\u00a0You can push your single EXE to any target system regardless of Python being on that system or not, and your code will run.\u00a0\u00a0<\/p><p>The problem is that it is a self extracting archive so to speak.\u00a0 When you run the program, it self extracts in to a temporary folder for the\u00a0user or to a folder that you set with the &#8211;runtime-tmpdir option.\u00a0 It\u00a0then creates a folder that begins with _MEI followed by a process id number.\u00a0 Then the Python Interpreter and all the byte code and packages\u00a0are beneath that _MEI folder.\u00a0 Then it runs.\u00a0 Life is good.\u00a0 Well, life\u00a0is good until the Incident Response team or Team Blue realizes that\u00a0single executable files packaged by Pyinstaller are not normal on the\u00a0network and they decide to create a signature that alerts every time a\u00a0folder is created that begins with _MEI. \ud83d\ude41<\/p><p>\u00a0At this point, you could move to the &#8220;one folder&#8221; option with\u00a0Pyinstaller instead of creating a &#8220;one file&#8221;, but that is messy because\u00a0then you have to zip and unzip files.\u00a0 It is not as clean to use in\u00a0social engineering\/phishing attacks either.\u00a0 If you can code in other\u00a0languages, you can always go that route.\u00a0 In my case, I know some C and\u00a0C# but I have to admit, once learning Python and having access to so\u00a0many amazing third party modules, it is hard to start a project with\u00a0anything but Python.\u00a0 PowerShell is also a possibility but it seems to\u00a0be heavy on the Incident Response radar, so I try to avoid it for\u00a0anything serious.<\/p><p>The obvious answer is to change the _MEI to something else.\u00a0 I first\u00a0tried to use a hex editor to find MEI in the one file executable and I\u00a0was going to change it there, but that isn&#8217;t going to work.\u00a0\u00a0 However,\u00a0after some research I learned that you can compile the Pyinstaller\u00a0bootloader yourself and if you can do that, then we should be able to<br \/>replace that _MEI in the code there and that is what I ended up doing\u00a0and it worked like a charm!\u00a0 Team Blue keeps looking for _MEI folders\u00a0being created but Team Red is using _JMP or whatever we prefer, just not MEI!<\/p><p>1.\u00a0 First, update your version of pyinstaller to the very latest.\u00a0 Do\u00a0this within PyCharm or by using pip (pip install pyinstaller -U).\u00a0 I use\u00a0PyCharm exclusively for my projects and only drop out to the command\u00a0line and use pip if updating my system&#8217;s main Python packages.\u00a0<\/p><p>Reference this page for help:\u00a0 <a href=\"https:\/\/pyinstaller.org\/en\/stable\/bootloader-building.html\">https:\/\/pyinstaller.org\/en\/stable\/bootloader-building.html<\/a><\/p><p>If you are on Windows, you will need to have a C++ compiler installed. I use Visual Studio on my system.<\/p><p>2. git clone https:\/\/github.com\/pyinstaller\/pyinstaller.git<\/p><p>I brought mine down to C:\\Temp.\u00a0 I deleted it after a successful test.<\/p><p>3.\u00a0 You will need to move to the bootloader&#8217;s src folder (on my system:\u00a0 C:\\Temp\\pyinstaller\\bootloader\\src) and edit pyi_utils_posix.c and\/or pyi_utils_win32.c.\u00a0 Change MEI to whatever you prefer.\u00a0 I chose JMP for this example.\u00a0 You can search for MEI in the file and quickly find the right location.\u00a0 Here is the location in the pyi_utils_win32.c file:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-be8d2dd elementor-widget elementor-widget-image\" data-id=\"be8d2dd\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"647\" height=\"72\" src=\"https:\/\/offensivepython.com\/wp-content\/uploads\/2025\/02\/Capture1.png\" class=\"attachment-large size-large wp-image-601\" alt=\"Modified pyi_utils_win32.c file\" srcset=\"https:\/\/offensivepython.com\/wp-content\/uploads\/2025\/02\/Capture1.png 647w, https:\/\/offensivepython.com\/wp-content\/uploads\/2025\/02\/Capture1-300x33.png 300w\" sizes=\"(max-width: 647px) 100vw, 647px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-874c10b e-flex e-con-boxed e-con e-parent\" data-id=\"874c10b\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-4553499 elementor-widget elementor-widget-text-editor\" data-id=\"4553499\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>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:<\/p><p>python .\/waf all<\/p><p>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).<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e954330 elementor-widget elementor-widget-image\" data-id=\"e954330\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"357\" height=\"183\" src=\"https:\/\/offensivepython.com\/wp-content\/uploads\/2025\/02\/Capture2.png\" class=\"attachment-large size-large wp-image-602\" alt=\"\" srcset=\"https:\/\/offensivepython.com\/wp-content\/uploads\/2025\/02\/Capture2.png 357w, https:\/\/offensivepython.com\/wp-content\/uploads\/2025\/02\/Capture2-300x154.png 300w\" sizes=\"(max-width: 357px) 100vw, 357px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-b9ee767 e-flex e-con-boxed e-con e-parent\" data-id=\"b9ee767\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-d62e48e elementor-widget elementor-widget-text-editor\" data-id=\"d62e48e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>6. Then go to your installed Pyinstaller&#8217;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.<\/p><p>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.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-183512c elementor-widget elementor-widget-image\" data-id=\"183512c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"711\" height=\"175\" src=\"https:\/\/offensivepython.com\/wp-content\/uploads\/2025\/02\/Capture3.png\" class=\"attachment-large size-large wp-image-603\" alt=\"\" srcset=\"https:\/\/offensivepython.com\/wp-content\/uploads\/2025\/02\/Capture3.png 711w, https:\/\/offensivepython.com\/wp-content\/uploads\/2025\/02\/Capture3-300x74.png 300w\" sizes=\"(max-width: 711px) 100vw, 711px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-609ce86 elementor-widget elementor-widget-text-editor\" data-id=\"609ce86\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>7. Now you can build your program with the new Pyinstaller bootloader files in place.<\/p>\n<p>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:<\/p>\n<p>Program: C:\\Projects\\Python\\py_c2_get\\.venv\\Scripts\\pyinstaller.exe<\/p>\n<p>Arguments: -w &#8211;runtime-tmpdir &#8220;C:\\Temp&#8221; -F win_client.py<\/p>\n<p>Working directory: C:\\Projects\\Python\\py_c2_get<\/p>\n<p>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!<\/p>\n<p>And this one belongs to the Red Team! \ud83d\ude42<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>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\u00a0think that life is good.\u00a0 How nice is a simple one file executable that\u00a0contains Python itself, your code, and all of the supporting third-party\u00a0modules that your code [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-container-style":"default","site-container-layout":"default","site-sidebar-layout":"default","site-transparent-header":"default","disable-article-header":"default","disable-site-header":"default","disable-site-footer":"default","disable-content-area-spacing":"default","footnotes":""},"categories":[16,35],"tags":[40,41,39],"class_list":["post-599","post","type-post","status-publish","format-standard","hentry","category-obfuscation","category-offensive-tool","tag-_mei","tag-mei","tag-pyinstaller"],"_links":{"self":[{"href":"https:\/\/offensivepython.com\/index.php\/wp-json\/wp\/v2\/posts\/599","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/offensivepython.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/offensivepython.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/offensivepython.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/offensivepython.com\/index.php\/wp-json\/wp\/v2\/comments?post=599"}],"version-history":[{"count":14,"href":"https:\/\/offensivepython.com\/index.php\/wp-json\/wp\/v2\/posts\/599\/revisions"}],"predecessor-version":[{"id":616,"href":"https:\/\/offensivepython.com\/index.php\/wp-json\/wp\/v2\/posts\/599\/revisions\/616"}],"wp:attachment":[{"href":"https:\/\/offensivepython.com\/index.php\/wp-json\/wp\/v2\/media?parent=599"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/offensivepython.com\/index.php\/wp-json\/wp\/v2\/categories?post=599"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/offensivepython.com\/index.php\/wp-json\/wp\/v2\/tags?post=599"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}