A note about containers

Apfell and containers

Apfell uses docker containers to logically separate different components and functions. There are three main categories:

  1. Apfell's main core. This consists of three docker containers stood up with docker-compose:

    1. apfell_apfell - An async python3 Sanic instance

    2. apfell_postgres - An instance of a postgresql database

    3. apfell_rabbitmq - An instance of a rabbitmq container for message passing between containers

  2. Command and Control (C2) Profiles

    1. Any folder in Apfell/C2_Profiles will be treated like a docker container specific to C2 profiles (more on this in the C2 section).

  3. Payload Types

    1. Any folder in Apfell/Payload_Types will be treated like a docker container specific to a payload type (such as apfell-jxa, viper)

To stop a specific C2 Profile's container, run sudo ./stop_c2_profiles.sh {c2_profile_name} or sudo ./stop_c2_profiles.sh to stop all of them.

To stop a specific Payload Type's container, run sudo ./stop_payload_types.sh {payload_type_name} or sudo ./stop_payload_types.sh to stop all of them.

If you want to reset all of the data in the database, use sudo ./reset_postgres_database.sh. Similar to if you want to clear out certain aspects of other containers, there will be a corresponding reset script.

Apfell shares the networking with the host it's on. This allows Apfell to not worry about exposing specific ports ahead of time for each container since they can be dynamically set by users. However, this does mean that Apfell needs to run as root if any ports under 1024 need to be used.


Apfell's architecture is broken out in the following diagram:

Apfell Architecture

Operators connect via a browser to the main Apfell server. This server is a Sanic, python3 web server. This main Apfell server connects to a PostgreSQL database where information about the operations lives. Each of these are in their own docker containers. When Apfell needs to talk to any payload type container or c2 profile container, it does so via RabbitMQ, which is in its own docker container as well.

When an agent calls back, it connects through these c2 profile containers which have the job of transforming whatever the c2 profile specific language/style is back into the normal RESTful API calls that the Apfell server needs.