Pyramid is composed of:
Pyramid is useful to perform post-exploitation task in an evasive manner, executing offensive tooling from a signed binary (e.g. python.exe) by importing their dependencies in memory. This can be achieved because:
For more information please check the DEFCON30 - Adversary village talk "Python vs Modern Defenses" slide deck and this post on my blog.
This tool was created to demostrate a bypass strategy against EDRs based on some blind-spots assumptions. It is a combination of already existing techniques and tools in a (to the best of my knowledge) novel way that can help evade defenses. The sole intent of the tool is to help the community increasing awareness around this kind of usage and accelerate a resolution. It's not a 0day, it's not a full fledged shiny C2, Pyramid exploits what might be EDRs blind spots and the tool has been made public to shed some light on them. A defense paragraph has been included, hoping that experienced blue-teamers can help contribute and provide better possible resolution on the issue Pyramid aims to highlight. All information is provided for educational purposes only. Follow instructions at your own risk. Neither the author nor his employer are responsible for any direct or consequential damage or loss arising from any person or organization.
Pyramid's in-memory loading was initially inspired and expanded upon xorrior 's Empyre - Finder Class
snovvcrash built the modules mod-DonPAPI.py - mod-LaZagne.py - mod-clr.py
Pyramid modules capabilities can be executed directly from a Python interpreter and are currently:
Pyramid HTTP server main features:
on-the-fly encryption (chacha,xor) of files to be delivered
auto-generation of Server configs based on pyramid command line
decoding and decryption of HTTP parameters (URL)
Basic HTTP Authentication
Cradle main features:
Downloading, decryption and in-memory execution of Pyramid modules.
Python-standard-libraries-only dependancy
Pyramid can be used with a Python Interpreter already existing on a target machine, or unpacking an official embeddable Python package and then running python.exe to execute a Python download cradle. This is a simple way to avoid creating uncommon Process tree pattern and looking like a normal Python application usage.
In Pyramid the download cradle is used to reach a Pyramid Server via HTTP/S to fetch modules and dependencies.
Modules are specific for the feature you want to use and contain:
The Python dependencies have been already fixed and modified to be imported in memory without conflicting.
There are currently 8 Pyramid modules available:
git clone https://github.com/naksyn/Pyramid
Generate SSL certificates for HTTP Server:
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365
If you want to use your own signed SSL certificate be sure to:
As an example, if you want to use pythonmemorymodule with Pyramid, put your payload in the Delivery_files folder, then open pythonmemorymodule.py and configure the needed parameters in the top of the script, such as the name of the payload file and the procedure you want to call after the PE has been loaded.
Once the Pyramid server is running and the Base script is ready you can set the variable pyramid_module
in Agent/cradle.py file and execute it on the target.
The cradle is built to be run with python standard libraries.
Example of running Pyramid HTTP Server using SSL certificate providing Basic Authentication, encrypting delivery files using ChaCha and auto-generating server configuration in modules and printing a pastable cradle for pythonmemorymodule:
python3 pyramid.py -p 443 -ssl -u testuser -pass Sup3rP4ss! -enc "chacha20" -passenc "TestPass1" -server "192.168.1.2" -generate -setcradle pythonmemorymodule.py
Upon startup pyramid.py will parse its own folder structure to look for key.pem, cert.pem and will deliver files from Server folder.
https://github.com/naksyn/Pyramid/assets/59816245/4fbc997e-af2d-4ead-881b-ee108c91d195
To execute Pyramid without bringing up a visible python.exe prompt you can leverage pythonw.exe that won't open a console window upon execution and is contained in the very same Windows Embeddable Package. The following picture illustrate an example usage of pythonw.exe to execute base-tunnel-socks5.py on a remote machine without opening a python.exe console window.
Dynamically loading Python modules does not natively support importing .pyd files that are essentially dlls. The only public solution to my knowledge that solves this problem is provided by Scythe (in-memory-execution) by re-engineering the CPython interpreter. In ordrer not to lose the digital signature, one solution that would allow using the native Python embeddable package involves dropping on disk the required pyd files or wheels. This should not have significant OPSEC implications in most cases, however bear in mind that the following wheels containing pyd files are dropped on disk to allow Dinamic loading to complete: . Cryptodome - needed by Bloodhound-Python, Impacket, DonPAPI and LaZagne . bcrypt, cryptography, nacl, cffi - needed by paramiko
Python.exe is a signed binary with good reputation and does not provide visibility on Python dynamic code. Pyramid exploits these evasion properties carrying out offensive tasks from within the same python.exe process.
For this reason, one of the most efficient solution would be to block by default binaries and dlls signed by Python Foundation, creating exceptions only for users that actually need to use python binaries.
Alerts on downloads of embeddable packages can also be raised.
Deploying PEP-578 is also feasible although complex, this is a sample implementation. However, deploying PEP-578 without blocking the usage of stock python binaries could make this countermeasure useless.