RedFiber

Overview

RedFiber is the Red-Team implant for Windows developed and maintained by Retooling. Written in C and compiled for the Intel x64 architecture, it is fully integrated with the Revo platform.

The integration is performed by the RedFiber Translator that interconnects the impant's custom protocol with the Revo's backend translating the messages into the target data model. The communication on the backend is done through the gRPC protocol.

Architecture. RedFiber and the Revo's architecture

RedFiber components (the implant and the translator) rely on Revo's Offensive Security Data Model (as shown in the figure below). There are no special features offered by the platform that are not exposed to third-party implant developers. This means that any third party implant will play on the same field as RedFiber. However, RedFiber offers several extension points that allow for the extremely faithful reproduction of potentially any threat actor's backdoor.

Revo's stacked view

Build Customization Paths

Each time a Revo's user wants to use our implant in an engagement he has to create a new build. The build is performed on our servers through the RedFiber dedicated BuildBox where the user has several options at his disposal.

RedFiber has several build customization paths, allowing the user to craft an implant that he can adapt to different scenarios (see the BuildPaths figure). Each path moves through different customization layers.

BuildPaths. The RedFiber build customization paths

The first customization layer is on the Binary Format. You can decide to build the implant either as an Executable or as a Reflective dll. This flexibility supports different scenarios, whether you need to drop the executable into a folder or inject it into a target process.

The second customization layer concerns the Feature set that you want to include into the build. At this layer, RedFiber has two different options:

  1. full-fledged, with the whole command set built-in or,
  2. unplugged, which is equipped only with the core command set which includes (but is not limited to!) the load and the inject commands. The capabilities of unplugged can be extended by using the load command (see next sections)

The third layer allows to select the Communication channel. Currently RedFiber supports two different communication channels:

  1. Http: The communication protocol is encapsulated into HTTP messages. This is used for the communication between RedFiber and its Translator
  2. Pipe: The communication protocol is encapsulated into SMB messages, through Named Pipes. This is used for implant-to-implant communications

RedFiber's Translator interconnects the implant with the Revo's backend.

RedFiber Core

The RedFiber core functionalities include:

  1. In-memory storage: used to maintain temporary information derived from the execution of tasks or modules
  2. Task manager: allow to define tasks that span for a user defined time-frame with a user-defined delay
  3. Injection: allow to inject modules into different processes
  4. Loader: allows to dynamically load new components into the current process.

In addition to the aforementioned features the RedFiber core implements commonly adopted OPSEC practices to avoid detection/analysis such as code obfuscation, string encryption and dynamic api resolution.

RedFiber modules

ManifestOverview. The RedFiber manifest in Revo

A module into RedFiber is an zip archive that contains two files:

  1. a manifest.json that describes the content of the module providing general information such as the version number or the module id and,
  2. a payload that contains the object that will be sent to RedFiber though the load command

An overview of the manifest.json is represented in Figure ManifestOverview. A little clarification before we continue with the discussion: what is presented here are the parts of the manifest that impact or are used by RedFiber or its modules. Note that the manifest can be extended at will when developing a custom implant; however, we do not cover that use case here.

To be correctly processed by Revo, a manifest must contain a set of top-level attributes:

  • family: a string that identifies the implant's family (lowercase redfiber in this case). This allows the Revo platform to manage things correctly when handling multiple implant families, such as preventing to load the wrong module (one designed for a different family) to an implant
  • staticPayloadPath: a string containing the path (relative to the archive root) of the payload
  • version: a string in the form YYYYMMDD and identify the version of the module
  • core: a boolean that allows to distinguish among implants and module. This will be typically set to false unless you are developing a custom implant for Revo. All redfiber customization paths have this set to true
  • type : identify the type of module implemented by the payload

RedFiber supports several module types:

  • Implant: an executable that can communicate with a RedFiber Revo Translator
  • Reflective: a reflective implant that can communicate with a RedFiber Revo Translator
  • BOF: a Beacon Object File
  • Dll: a module that the implant can dynamically load
  • Loader: a Dll that implements a custom loader
  • Custom: modules that are handled by custom loaders. This allows third-party developers to implement their own custom file format to be delivered to the target. The corresponding Loader will do the magic
  • Extension: a special module that provide a custom implementation of a set of commands for an implant. Third party developers can provide their own command sets implementations.

The manifest fields change according to the module type, as shown in Figure ManifestOverview. Each type offers different capabilities in terms of ease of development, payload size, stealthiness, and functionalities.

Type DLL

The RedFiber loader can load standard DLLs. When loaded without parameters, the DLL is loaded directly from memory, and the DllMain function is invoked. After DllMain returns, the output is sent back to the Translator, and the DLL is unloaded.

However, RedFiber also supports making a DLL persistent in memory using the --persistence parameter (or, by enabling the switch button from the web ui). In this case the DLL is not unloaded after the DllMain returns and its exports can be invoked through the invoke command.

The same result (loading a dll and invoking its exports) can be done from the Revo UI as shown in the following sequence of screens.

DllLoadOverview. The loading procedure can be triggered by clicking on the *Load module* button.

DllLoadModule. Allows to load a module from the Module list. The flag Memory persistence can be activated.

DllLoadModuleDone. The module has been loaded. The returned value is a handle used by the platform to refer to the loaded module

DllModulesOverview. The module `dllechoascii` has been addedd to the list of loaded modules. Its exports can be invoked by clicking on the corresponding `fx` icon.

DllInvokeExport. The Invoke of the export EchoAscii (number 1)

The manifest.json of the dellechoascii module is reported here:

{
  "name": "dllechoascii.dll",
  "type": "dll",
  "version": 20240617,
  "persistence": 1,
  "desc": "Echo dll ASCII version",
  "staticPayloadPath": "dllechoascii.dll",
  "family": "redfiber",
  "tags": [
    ""
  ],
  "exports": [
    {
      "name": "EchoAscii",
      "desc": "The EchoAsciiModule",
      "prototype": "LPSTR EchoAscii(int dummy, const LPSTR lpString)",
      "ordinal": 1,
      "params": [
        {
          "name": "szSize",
          "type": "int32",
          "default": "0"
        },
        {
          "name": "lpString",
          "type": "string",
          "mandatory": true,
          "desc": "The string to be echoed"
        }
      ]
    }
  ]
}

The group exports allows to declare the exports of the DLL. For each export the set of params are defined as a ordered array (the position is relevant and must preserve what is defined in the prototype). Each element of the array represents an argument for the function has its type.

The possible type values for params are:

ModuleParamTypeInt16   = "int16"
ModuleParamTypeInt32   = "int32"
ModuleParamTypeInt64   = "int64"
ModuleParamTypeBoolean = "bool"
ModuleParamString      = "string"
ModuleParamWString     = "wstring"

Type Extensions

Extensions in RedFiber are organized into command sets. A command set group together commands that target a specific subsystem (e.g. filesystem vs registry). Each time a new command set is loaded into the implant (typically unplugged), new commands become available into the implant.

The following command sets are present into the platform:

  1. Info: Implements the process list command
  2. Filesystem: Implements the filesystem access capabilities (including chunked upload and download of files)
  3. Inter-process communication: Implements the capability to link to another implant.
  4. Screenshot: allows to take screenshots of the target machine
  5. Clipboard: implements clipboard capture
  6. Execution: allow to create process on the remote machine
  7. Token: implements the access token manipulation
  8. Shell: implements an emulated PowerShell console that can be used to run arbitrary commands/scripts on the target

Type Beacon Object File (BOF)

Beacon Object File (BOF) is a specialized form of object file used primarily in the context of penetration testing. The following points summarize BOFs:

  1. Purpose: BOFs are used to extend the functionality of an host implant to implement a feature that is not immediately present on the implant. They can help in maintaining the memory detection surface smaller by exposing only a minimal feature set

  2. Format: BOFs are typically written in C and compiled into position-independent code (PIC), which means they can be loaded at any memory address without modification. This makes them suitable for injection into the host implant.

  3. Advantages:

    • Stealth: BOFs are smaller and less likely to be detected than traditional binaries.
    • Efficiency: They allow for quick execution of custom code without the overhead of compiling and deploying full binaries.
    • Flexibility: Security professionals can rapidly develop and deploy new functionalities tailored to specific engagement requirements.
  4. Development: Writing BOFs involves:

    • Creating C code that implements the desired functionality.
    • Compiling the C code into a BOF using a cross-compiler or a specialized compiler (such as mingw or others) configuration to ensure the code is position-independent.

RedFiber supports the loading and the execution of BOFs. An interesting thing about The RedFiber BOF loader, consists in the fact that the output provided by a running BOF is captured by RedFiber and than sent back to the Translator in chunks. To obtain this result the behavior of the functions that typically write on the stdout such as BeaconOutput or BeaconPrintf have been modified.

This enables to send even binary files (e.g. the memory dump of a target process) back to the Redfiber Translator, no matter what size the output is (up to ~500MB). Also, thanks to its multi-threaded design, RedFiber can run multiple BOFs concurrently and still receive and process built-in commands.

The following snippet contains an example of a BOF manifest that takes in input 5 parameters:

{
    "type": "bof",
    "version": 20240402,
    "name": "reg_query.x64.obj",
    "description" : "Query or enumerate a registry path ",
    "architecture" : "x64",
    "staticPayloadPath": "reg_query.x64.obj",
    "family" : "redfiber",
    "exports": [ {
        "name": "go",
        "prototype": "string fn(string Host, int32 Hive, string Path, string Name, bool Recurse)",
        "ordinal": 1,
        "params": [
          {
            "name": "Host",
            "type": "string",
            "description" : "The remote host (leave empty for localhost)"
          },
          {
            "name": "Hive",
            "type": "int32",
            "description" : "1=HKCU 2=HKLM"
          },
          {
            "name": "Path",
            "type": "string",
            "description" : "The registry path to query or enum"
          },        
          {
            "name": "Name",
            "type": "string",
            "description" : "The valuename"
          },
          {
            "name": "Recurse",
            "type": "bool",
            "description" : "(Only if enum) True or False if recursive search should be enabled"
          }
      ]
   }]
}

The manifest is very similar to the DLL despite the fact that:

  • persistence must be disabled
  • only one export can be declared
  • the export should be named go

And this is how it appears into the WebUI:

Communication Channels

HTTP

The communication with the Translator uses a custom protocol based on HTTP. Both http and https are supported.

Configuration form for RedFiber http

SMB

A second communication channel is support which is bases on named pipes and the SMB protocol. This enables P2P communication between implants. The communication in this case occur through the SMB protocol.

Configuration form for RedFiber pipe

Channel swap and custom channels

Either if you are in the middle of a Red-Team engagement or if you want to emulate a threat actor you may need to perform a channel swap, namely modify communication protocol and parameters. In its simplest form, the channel swap can be used to change the parameters of an existing channel that cannot be changed using the standard config command of the web ui. For instance if you have activated the certificate pinning you cannot change the hash of the translator's certificate at runtime. However channel swap enables a complete substitution of the communication protocol while the implant is running such as moving from an http-based communication to a completely custom transport protocol.

We use it for adversary emulation but this capability is exposed even to third parties. To do this you simply have to create a DLL module with a manifest like the following one:

{
    "id": 2000,
    "version": 20231218,
    "type": "module",
    "core": false,
    "name": "httpchannel",
    "family" : "redfiber",
    "description" : "Implements http channel with embedded configuration",
    "staticPayloadPath" : "http_dll.dll",
    "commands": []
}

Injection techniques

The reflective version can be injected by any of the supported techniques. Both the unplugged and the full version of RedFiber can be injected though the injection form (or, if you prefer the command line, with the inject command from the console).

The injection techniques are organized into writing and execution primitives. The former specifies how memory should be allocated in the target process, while the latter indicates how execution should be triggered.

The current version supports, the following writing privimitives:

  1. MapViewOfSection: based on the corresponding WINAPI
  2. VirtualAllocEx: based on the corresponding WINAPI
  3. DripAllocator: a custom implementation of the DripLoader
  4. MapViewOfFile: based on the corresponding WINAPI

along with the following execution primitives:

  1. CreateRemoteThread: based on the corresponding WINAPI
  2. RtlCreateUserThread: based on the corresponding WINAPI
  3. TpDirectInsertion: ThreadPool injection based on the corresponding WINAPI
  4. TpJobInsetion: ThreadPool injection based on the corresponding WINAPI
  5. TpAlpc: ThreadPool injection based on the corresponding WINAPI

And, this is the compatibility matrix between writing and execution primitives:

mem/run MapViewOfFile MapViewOfSection VirtualAllocEx DripAllocator
CreateRemoteThread ok ok ok ok
Zberp ok ok Unsupported ok
RtlCreateUserThread Unsupported ok ok ok
TpDirectInsertion Unsupported ok Unsupported Unsupported
TpJobInsetion Unsupported ok Unsupported Unsupported
TpAlpc Unsupported ok Unsupported Unsupported

note TpDirectInsertion, TpJobInsetion, TpAlpc also requires SeDebugPrivilege enabled. If the token of the RedFiber process has the SeDebugPrivilege, the command token-set-privileges can be used to enable it.

Stomping

Module stomping, also known as DLL hollowing, is a malware technique where an attacker injects malicious code into the memory space of a legitimate DLL, effectively "hollowing out" its original code.

The injection forms allow specifying which DLL to stomp into the target process. This is a safe operation as long as certain rules are respected:

  1. The target process must not be using the DLL you select as the target for stomping.
  2. The .text section of the target process must be large enough to contain the RedFiber .text section.

Since the injector implements a Control-Flow Guard (CFG) bypass, you can select any system DLL as the target.

Also, you do not have to worry about scaring RWX, none of them will be left behind.

Obfuscation

Each time a new build is created through the RedFiber Buildbox, several obfuscation transformations are applied to the implant. These transformation include Control flow Graph flattening, opaque predicates with dead code injection, constant obfuscation with mixed boolean-arithmetic expressions and string encryption. The obfuscation is unique because the obfuscator takes several random choices while performing its duties on a build unit. This make cross-correlation of different builds and the creation of through detection rules more difficult to be done.

Supported Versions

It supports Windows 10 starting from version 1703 and all versions of Windows 11.