How it works
The backend of MultiLoader is a simple REST API that allows you to upload files, upload loader options and download the files with the loader options applied. The frontend is a simple web interface that allows you to interact with the API. The frontend is built using simple html, css and javascript. The backend is built Flask, a python web framework.
Architecture
The architecture of MultiLoader is simple. A web client interacts with the backend API to upload files and loader options. The backend API stores the payload in a temporary directory with the name of the session id. The session id is a unique identifier for the session created by the user. The session id is used to identify the related files and loader options. The backend API then processes the files with the loader options and stores the processed files in the temporary directory. The processed files are then available for download by the user.
Components
Frontend
The frontend is a simple web generated with the help of Jinja2 templating engine. It is dynamically generated based on the plugins available in the backend. The frontend presents a set of options to the user, each one representing a plugin. The user can choose the plugin and upload the files to be processed. The frontend then sends the files to the backend API for processing and queries the backend API for the processed files.
Backend
The backend provides a REST API for the frontend to interact with. The backend API is built using Flask, a python web framework. The backend API provides the following endpoints:
/api/v1/plugins
: Get the list of available plugins/api/v1/payload/upload/<id>
: Upload the files to be processed/api/v1/payload/generate/<id>
: Generate the loader with the options provided in a json array/api/v1/payload/status/<id>
: Get the status of the payload, whether it is processed or not/api/v1/payload/download/<id>
: Download the processed files
The ID in the endpoints is the session id generated by the frontend. The session id is used to identify the related files and loader options and should be base62 or similar encoding.
A flowchart of the process is shown below:
sequenceDiagram participant Frontend participant Backend participant Worker Backend->>Backend: Load plugins Frontend->>Backend: Get available plugins Backend->>Frontend: Return available plugins Frontend->>Frontend: Generate options based on plugins Frontend->>Frontend: Generate UUID Frontend->>Backend: Upload payload Backend->>Backend: Store payload in temporary directory Frontend->>Backend: Upload loader options Backend->>Worker: Request payload processing Worker->>Worker: Set payload processing status Frontend->>Backend: Request Status Backend->>Frontend: Return status of payload Worker->>Worker: Process payload Frontend->>Backend: Request Status Backend->>Frontend: Return status of payload Worker->>Worker: Set payload processing status Frontend->>Backend: Request Status Backend->>Frontend: Return status of payload Frontend->>Backend: Download processed files Backend->>Frontend: Return processed files Backend->>Backend: Delete temporary directory
Plugins
The plugins are the core of MultiLoader. The plugins are python scripts that process the files on the temporary directory. The plugins are stored in the plugins
directory in the backend. The plugins are loaded dynamically by the backend API on the start of the server.
There are 5 types of plugins:
keying
: Keying plugins are used for payload execution prevention, they responsible for checking the environment and setting guardrails before the payload is executed.payload_mods
: Payload mods plugins are used for modifying the format of the payload that is stored inside the loader, they can be obfuscation, compression, encryption, etc.execution
: Execution plugins are used for executing the payload, the user is only allowed to select one execution plugin and this plugin is responsible for executing the payload in memory.pre_comp
: Pre-compilation plugins are used for modifying the loader code before it is compiled, this can be used for adding additional metadata, reducing entropy, etc.post_comp
: Post-compilation plugins are used for modifying the compiled loader, this can be used for junk code insertion, signature generation, etc.
The plugins are executed in the order presented above. The types of plugins have subtypes under them. The subtypes can be user defined and can be added to the plugin by the user, their presentation is done dynamically by the frontend. The plugins execution only respects the order of the types and not the subtypes.
Users can create their own plugins and add them to the plugins
directory. The plugins should be python scripts that following structure:
def desc():
return "Description of what the plugin does"
def run():
# Your code here
return
The desc
function should return a string that describes what the plugin does. The run
function should contain the code that processes the files. The run
function should process the files in the temporary directory and store the processed files in the temporary directory.
To add the plugin to the backend, the user should add the plugin to the plugins
directory under the right type and subtype. The plugin should be inside a directory with the name of the plugin and the python script should be named run.py
. An example of the plugin structure is shown below:
$ tree plugins
.
├── execution # Type
│ ├── local # Subtype
│ │ ├── CreateThread # Plugin name
└── run.py # Plugin script
<SNIP>
After adding the plugin, the user should restart the backend API for the plugin to be loaded. An example of this can be seen in the video below: