Und3rf10w

My random rants and ravings

8 January 2022

Shlyuz Implant Framework: Part 1 - Influences

by Und3rf10w

Overview

I’m excited to finally discuss and share the Proof-of-Concept code for an implant framework I wrote called Shlyuz (шлюз). Shlyuz takes a number of design queues from the Assassin Implant developed by the Central Intelligence Agency as described in the Vault7 Leak from WikiLeaks. Some additional inspirations were taken from some other projects and presentations such as the excellent Flying a False Flag presentation from Blackhat 2019 by Nick Landers, among others.

Disclaimer: For reasons that should be obvious, I will not be directly linking to WikiLeaks in this post, but I may embed images or make references to various leaked classified documents. Do with that warning what you will.

Prior to releasing the source code of the Shlyuz framework, I’ll be releasing a series of posts that cover some background, design decisions, and lessons learned. This first, particular post will not dive into much into Shlyuz itself yet, but that will be done in future posts of this series.

Why write this?

I’ve written before about my belief that implementing a C2 is a a great way to get familiar with a programming language. At the time I wrote Shlyuz, I considered myself to be not even a decent programmer. Writing Shlyuz provided me the opportunity to explore a number of concepts that I wanted to get more familiar with such as:

These are quite lofty goals, especially for someone that’s a self-taught programmer, but this seemed like the perfect project to attempt to learn and combine some about these concepts through implementation and design.

I’m a huge fan of system design that is as deniable as possible, and Vault 7 provided a rare window of opportunity to understand how groups that rely on this concept implement it.

Assassin - The Shlyuz Design Inspiration

Before I dig into Shlyuz itself, I think it will be helpful to get a solid understanding of the design inspiration that led to the creation of Shlyuz, which again, as previously mentioned was Assassin.

The Assassin user guide Concept of Operations describes it as:

…an automated Implant that provides a simple collection platform on remote computers running the Microsoft Windows operating system. Once the tool is installed on the target, the implant is run within a Windows service process. Assassin will then periodically beacon to its configured listening post(s) to request tasking and deliver results. Communication occurs over one or more transport protocols as configured before or during deployment

I interpreted that as being straightforward; a Windows implant talks to LPs (listening posts), gets tasks and delivers results. Basically sounds like literally every other implant. One thing that stuck out to me though was the last sentence in the concept of operations: “Communication occurs over one or more transport protocols as configured before or during deployment”. (Emphasis mine).

Having an implant capable of communicating over multiple transport protocols that can be swapped sounded intriguing to me, so I dove further into its capabilities.

Galleon Standard

Assassin subsystems are apparently compliant with a set of standards called Galleon, which provides a specification for allowing a system to have a layed architecture and has interfaces for logging, transport, and publishing.

The Galleon architecture can be represented as:

Galleon Architecture

I like this model, as it promotes dividing the system into components in each layer.

In addition, the Galleon model has three standard interfaces (as taken from Galleon-Design.pdf):

Interface Description
Transport Provides services for the transmission of data between components in a Galleon system. This allows components to interact between machines without knowing any details of network or machine configuration.
Publish Provides a mechanism for processing and exporting data from a Galleon system. System components will be able to post data to the system without any awareness of how that data will be handled by the system
Log Provides a mechanism for recording events that occur in a Galleon system

Galleon interfaces expose their functionality through handlers, which are called by executables, which implements the appropriate interface.

Frankly, I wasn’t interested in “recreating Assassin”, but this was a neat model to use for inspiration.

Galleon Transport Interface

With one of my interests being weird ways to do transport channels, it’s a useful exercise to gain an understanding of what a Galleon Transport Interface might look like. Transport interfaces are “…used to transmit arbitrary data between components that may or may not be on the same machine”.

Rather than trying to explain the transport process myself, showing an excerpt of the design document would be more advantageous:

Galleon Transport Design Galleon Transport Labels

This logic can also be represented as the following sequence diagram:

Galleon Transport Sequence Diagram

An important takeaway that’s mentioned here is:

The interface does not provide any guarantees of delivery or service level. All data transmitted through the interface is treated with the same priority. If a client requires guaranteed delivery, they can build a reliable protocol on top of the Transport Interface. For example, build a super layer implementing an Automatic Repeat reQuest (ARQ) scheme

There wasn’t much in the way of what their ideal ARQ scheme might look like, but one can likely assume it relies on retying the transaction. Keep in mind this document is fairly old, one concept I would like to dig further into is verification that the data received is the data that was actually expected.

Galleon Publish Interface

The publish interface is used to post data that’s ready for further processing or operator consumption. It “…provides an abstraction… used to process, store, and disseminate data collected or generated by the system”.

Galleon Publish Design Galleon Publish Miscellaneous

Essentially, the client generates some sort of data, calls the post and publish handlers, the publish interface routes it to the appropriate ingestor(s), and the ingestor does the whatever action it requires, all while maintaining the source and type of data being posted.

This is a fairly logical and easy to understand pipeline that allows for accurate auditing of data as it moves through the system.

Galleon Log Interface

The log interface… describes how to do logging… There’s really nothing revolutionary here, so it’s really not even worth reviewing for the purposes of this post.

Assassin Subsystems

Now that we have an understanding of the standards that Assassin had to conform to, we can look at the components (referred to as subsystems) of the framework:

Shlyuz Subsystems

I liked the model somewhat implemented by Assassin, but I wanted to go further and landed on a model for Shlyuz components that went further in segmenting components; taking additional design cues from shadow and Cobalt Strike. I’ll quickly touch on the various Shlyuz components, but will dig further into the Shlyuz architecture in a future post.

Again, quite similar to the Assassin design, but a bit more segmented.

Assassin Multi-platform support

Section 1.4.2 lets it be known that Assassin scripts are written for Python 3.3, and that these scripts may run on any platform and operating system that runs a Python interpreter. This was great news to me at the time as I knew I wasn’t crazy for thinking I could implement this in Python.

The Assassin Implant

The Assassin Implant itself is what provides functionality of the toolset on the target machine it is running, “including communications and task execution”. There are a number different deployment methods available, as described in sections 2.1 to 7.1.3 in the Assassin user guide. Having all of these options is great, but since I don’t have the resources of taxpayers at my disposal, I didn’t really care about making a number of different deployment options available for Shlyuz. I do recommend you review their deployment options however, as it’s a pretty good read.

Implant Identification

As described in section 7.2, each Assassin implant contains a case-sensitive, eight-digit string that uniquely identifies each implant. The ID contains two parts, the parent and child. The parent identifies the group of implants set by the operator at build time, and the child is randomly generated on first execution unless otherwise defined.

By having an implant have a parent ID, they are restricted to only allowing one implant to execute on a host per parent ID.

My personal hypothesis is that the parent ID is likely used to identify either the target environment or “campaign” that the implant is being used on. The only drawback I see to this approach is handling cases where you have to execute another implant in order to obtain higher privileges, but I’m sure they accounted for that.

Implant Beaconing

Like most implants, Assassin communications are organized around periodic beacons. During a beacon event, it connects to the LP ands sets information about the state, checks for tasks, and responds with results. This is primarily covered in detail in section 7.3 of the user guide, but the beaconing model is very similar to most modern beacon implementations.

A few interesting points to note though:

Section 7.3.1.2 describes the manifest of data sent to the LP during a beacon event:

The last point is interesting as it signifies the capability for an implant to use different transport mechanisms.

Beacon Timing

Section 7.3.2 describes beacon timing with the following algorithm:

if (comms_succeeded):
    interval = default_interval
else:
    interval *= backoff_factor
    interval += RandomInteger(-jitter, jitter)
if (interval > max_interval):
    interval = max_interval

An interesting feature of Assassin I haven’t really seen much in other frameworks is the backoff_factor, which modifies the interval after a failed attempt to beacon.

Also mentioned, but not present in the given algorithm, is the initial_wait variable, which describes how long the implant must wait after startup prior to attempt it’s initial beacon.

Implant Tasking

If there’s one lesson I learned writing Shlyuz, it’s that asynchronous tasking is fucking hard! Thankfully, section 7.4 goes into extensive detail on how tasking works within Assassin, which gave me some insight on how to implement it for Shlyuz.

A task consists of one or more commands, which are the executed in sequence until they are all executed, or until an error is detected. A task can be used to encapsulate several interdependent commands.

A task can be set to run on receipt or run on startup.

I really like the idea of run on startup, but an improvement I would make to the tasking is providing the ability for a task to soft fail instead of always doing a hard fail. For example, if the operator issues a series of tasks, and for some reason one of those instructions encounters an error, all following instructions will not execute. This is not always ideal from an operator perspective.

Finally, a task can be configured to push results immediately to the LP.

Section 7.4.3 describes that an operator can also add tasks outside of the framework by placing it in the relevant startup or input directory, depending on whether they want the task to run on receipt or run on startup.

Tasks are described as blocking; another feature improvement I’d suggest would be to set tasks to be the introduction of a flag that allows a task to be able to execute asynchronously, not blocking the execution of subsequent task(s).

Implant Communication

Section 7.5.1 describes how an implant can be configured to communicate using one or more transports. An implant is configured with an ordered list of transports, and the implant will attempt to iterate through them in the event of a failure. It is not clear whether this list of transports can be modified after execution.

Implant transports are done soley over HTTPS using the WinInet API with Firefox user agents.

As described in section 7.5.4, Assassin has a chunking feature, allowing the operator to set a limit on the amount of data that’s uploaded from the implant to the LP during a transaction. There is a hard limit of 1GB chunks.

Finally, of note is section 7.6.3, which describes a failure threshold feature. If the implant fails to communicate more than the configured number of times, the implant will automatically uninstall itself from the target.

Implant Configuration

Section 7.7 describes how implant configurations work.

7.7.1 says that an implant has 3 configuration states, running, persistent, and factory:

State Description
Running Settings the implant is using to operate. Stored in memory and lost when the implant restarts.
Persistent Settings the implant will revert to upon startup. Stored as a patch in the binary, otherwise saved as a file in the startup directory
Factory Settings the implant had when it was built and originally deployed. Can be reverted to this state at any time by the operator

Implant Crypto

Section 7.8 describes the cryptographic mechanism used by the implant. Basically it uses a modified RC4 stream cipher, and any data sent is encrypted prior to potential exposure. The implant carries a sixteen byte key that is patched into the binary. A sixteen byte session key is generated by combining a four byte nonce with the key and calculating the MD5 hash. A new key is calculated per crypto transaction, while the nonce is prepended to the crypt text before being stored or transmitted.

I found the constant rotation of the session key interesting and took some design inspiration from this model when writing Shlyuz.

The rest of the user guide basically covers the usage of the various components, installation, configuration, usage, and frequently asked questions. These sections are great if you’re trying to build an exact replica of Assassin, but that was not my intention with Shlyuz.

Shlyuz Design Goals

Armed with a general understanding of Assassin design and architecture, I started to get a vision of what I wanted the Shlyuz framework to look like and how to architect it.

The Shlyuz framework set out to accomplish a number of design objectives:

My thought was that modularization could be achieved through the implementation of common protocols between components. Ideally this protocol would allow for communication between individual components regardless of their implementation so long as they adhere to the protocol.

This common protocol should be designed to be auditable, scalable, authenticatable and generic enough to be reusable.

This common component protocol model provides a design target for various transport protocols. Transport protocols however had additional design targets:

Future posts will delve into the common protocol developed for Shlyuz, the cryptographic model, challenges I encountered, architecture, and the tasking and communication model. Stay tuned for more updates.

seo tags: shlyuz - vault7 - implant - penetration_testing - red_team - assassin - CIA