Table of Contents

A surprise to nobody, making your own C2 is a lot of work. This post is about the goals and overall architecture of my own lightweight C2 framework, the Diet-C2.

Goals

The main purpose of making my own C2 framework was to have a platform to learn redteam techniques in-depth by implementing them myself end-to-end. For example, writing my own ReflectiveLoader() and implementing reflective DLL injection entirely myself (with some references of course).

Along the way I hoped to get a better idea of how to use the WinAPI, as well as implement all the things I learn from Sektor7’s introductory and intermediate malware development courses in one project, and anything else I learn in the future.

Source Code

The source code can be found on my github, updated regularly.

Languages and Structure

Getting into the structure of Diet-C2, there are 3 parts: the operator client with a terminal user interface, a server that takes in the client commands and serves them up to the implant which processes them and replies with some output.

A brief description of some the larger libraries / technologies used for each part of the Diet-C2.

Server

  • Written in python
  • Uses Flask to serve an HTTPS server
  • One HTTPS listener on startup

Implant

  • Written in C++
  • Uses WinAPI and WinHTTP to reach out and execute commands from the server

Client

  • Written in python
  • Uses Textual for the terminal user interface
  • Uses requests library to interact with the server
  • Also hosts a small threaded Flask server to receive updates from the server

I wanted to support multiple clients, as well as multiple implants so I built out the foundation of the framework with that in mind. I thought about supporting multiple listeners on the same server, but since there is just the one type of listener, I am putting it off until I write a different listener.

Big Picture Plan for the Diet-C2

I came into this project with the intention of approaching it as a “infosec” project rather than a “development” project.

I wanted to focus primarily on the implementation of red team techniques rather than on exclusively software-engineering concepts like storing the data on the server properly using SQLite.

I am approaching this project from the start as a learning experience for the red team techniques, rather than a full C2 implementation like Sliver C2 or similar.

That being said, I still need to do some design and development work to get the Diet-C2 off the ground before I can easily add new commands. The rest of the post will deal with the design of the Diet-C2.

Building an Extensible Foundation

My goal for this milestone was pretty simple: be able to fully describe how I was going to send a command from the client, to the server and on to the implant, and how the output of the command was going to come back to the client.

I used the client, server and implant starting up as the beginning of my plan.

Here I’ll describe the what each endpoint is used for on the server, for who it is for, and how it works. Then in the next section, using the endpoints described below, Ill outline the general structure of how the whoami command is sent to the server, how the implant gets the command, and how the response arrives back to the client.

This is not an exhaustive list of endpoints, but these are all that are required to just send a simple shell command.

Endpoints for implants

  • /login
    • Receives implant login requests, and saves implant data in implant database
    • Sends an update to the currently connected operators that a new implant connected
    • Replies to the implant with a generated ID, unique to each implant
  • /recipes
    • Where the implant goes to check if there is a command in it’s queue
    • If there is a command, the server sends it back as a response
  • /comment
    • Where the implant goes to POST a commands output
    • The command output is forwarded along to the operator that sent the command

Endpoints for operators

  • /admin/login
    • Where the server processes operator client logins, and saves them to the operator database
    • It responds with a copy of the implant database in json to sync up with the client on login
  • /admin/management
    • Where the operator sends commands
    • Commands are processed, encrypted, and stored in the associated implant’s command queue for retrieval by the implant
  • /admin/update/implants
    • Where the operator goes to get a live sync of the implant database
    • The server responds with a copy of the implant database in json

There is additionally a Flask server running on the client with one endpoint, /update, created to receive updates from the server - such as a new implant, or a response to a command to update the client UI with the output.

Simple Command Flow

Beginning from the startup of the server, implant and client - a whoami command gets executed on the implant as follows.

For reference, shell specifies a cmd.exe command, executing everything following shell on the implant using cmd.exe on the implant, and then returns the output back to the client. For this example, the appropriate diet-client command would be shell whoami. The storage methods are also abstracted away, for simplicity.

The simplified flow is as follows

  1. Server is started
  2. Client logs in to the server at /admin/login
  3. Implant logs in to the server at /login
    • Server gets the request, adds the implant to the implant database
    • Server updates all connected clients by sending a copy of the implant data to their /update endpoints
    • Server responds to the implant with a generated unique implant ID
    • Implant starts the infinite loop of checking /recipes on the server for a command every X seconds
  4. Client receives the new implant update, and selects the implant they would like to send commands to with select IMPLANT_ID
    • The command reaches out to /admin/update/implants to sync the implant databases between the client and server to make sure the implant exists
    • If the provided IMPLANT_ID is valid, selects the implant
  5. Client then inputs the command shell whoami
    • A command ID is created, unique to this specific command
    • A command string is created, and consists of
      • Command ID
      • Command type
      • Command parameters
    • The command string is ::: delimited, and looks like this
      • ID_UNIQUECMD:::CMD_SHELL:::whoami
  6. Command string and what implant the command is for is sent to the server at /admin/management
    • The server processes the command string, and encrypts it using AES
    • Then adds the command string to the command queue of the associated implant
  7. Implant reaches out to /recipes to find a command, this time it finds one
    • The server looks for a command in the implants queue, and finds one, popping it off the queue and returns it to the implant
  8. The implant decrypts the command, and identifies it is as a shell command
  9. The implant runs the whoami command, and captures the output
  10. The implant then sends the command ID and the output of the command back to the server at /comment
    • For example, if the output was win10_pc\USER, the POST request to the server would be
      • ID_UNIQUECMD:::win10_pc\USER
    • The server forwards the message along to the client that made the command to their /update endpoint
    • The server responds with a success message to the implant
    • The implant goes back to querying /recipes for new commands every X seconds
  11. The client recieves the response to it’s command on /update, and prints the output of the command to the UI

I hope that made some sense.

Conclusion

Hopefully the structure of my framework is easy to understand, it is a fairly common implementation but the details are different of course. This article is a bit of a confusing read so I will update it in the future if I figure out a better way to describe my planning process.

Here is a screenshot of what the UI looks like on the client side with one implant connected, as well as how a shell command looks.

If you want to see the source code and my progress, you can find it on my github here

The next blog post won’t walk through all the code, but just some things I learned the way, and some (in my opinion) interesting design decisions I made for the implant, server and client as I was building foundational features of the Diet-C2.

Thanks for reading.