Reprogrammed

Let's Make Malware - Fiber Execution

Lets Make Malware

Preamble

This week, we will cover our first alternative to the common “VirtualAlloc/VirtualAllocEx -> WriteProcessMemory -> CreateThread/CreateRemoteThread” TTP.

For this, we will be utilizing fibers.

To start, we must cover what exactly a fiber is.

As defined by MSDN: A fiber is a unit of execution that must be manually scheduled by the application.

Fibers run in the context of the threads that schedule them. Each thread can schedule multiple fibers. In general, fibers do not provide advantages over a well-designed multithreaded application.

However, using fibers can make it easier to port applications that were designed to schedule their own threads.

Simply put, a fiber is another method of executing code. As a reminder, processes do not execute (run) code. Threads (typically) do.

This makes fibers similar to threads in that both are capable of running our shellcode (or any code, really) but distinct as they are their own entity.

What makes fibers special is that they can only be created by other fibers.

With that out of the way, let’s make malware.

We’ll use just five API calls, two of which we are familiar with already.

ConvertThreadToFiber

The first will be ConvertThreadToFiber. It does exactly what it says on the tin can and only takes one parameter.

MSDN defines this function like so:

LPVOID ConvertThreadToFiber(
  [in, optional] LPVOID lpParameter
);

It’s sole parameter is simply a pointer to any data we may want to pass to the fiber. In this case, there is none so we pass in NULL.

VirtualAlloc and memcpy

Next, we will use VirtualAlloc to allocate a memory buffer to hold our shellcode. This has been covered in prior posts, so we will not be going over it again.

Following this, We will use memcpy to move our shellcode into our buffer. This, too, has been covered previously.

CreateFiber

CreateFiber is our next function, and it should be self-explanatory. It creates another fiber that will execute our shellcode.

It is defined like so:

LPVOID CreateFiber(
  [in]           SIZE_T                dwStackSize,
  [in]           LPFIBER_START_ROUTINE lpStartAddress,
  [in, optional] LPVOID                lpParameter
);

The first parameter is the initial size of the stack in bytes. We will set this to 0, which simply uses the default size.

The second parameter is very similar to CreateThread’s third parameter. Here, we tell it what we want to execute. This is our buffer variable.

The last parameter is any parameter we want to pass along to lpStartAddress (the second parameter of this call). We do not have any, so we set it to NULL.

SwitchToFiber

Finally, the last API we will use is SwitchToFiber.

This function call is necessary because, unlike threads, only one fiber can run at a time. While CreateThread essentially both creates a new thread and starts it, CreateFiber only creates one. We need to use SwitchToFiber to start this new second fiber.

This function is defined as such:

void SwitchToFiber(
  [in] LPVOID lpFiber
);

Its parameter is, of course, the fiber we want to start. This will what our call to CreateFiber returns.

All Together

So, putting it all together, our codebase will look like this:

#include <windows.h>
int main() {
	// Meterpreter calc.exe payload
  unsigned char shellcode[] = { dont trust random blobs of shellcode you find on the internet };
  PVOID mainFiber = ConvertThreadToFiber(NULL);
  PVOID buffer = VirtualAlloc(0, sizeof shellcode, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  memcpy(buffer, shellcode, sizeof shellcode);
  PVOID pFiber = CreateFiber(0, (LPFIBER_START_ROUTINE) buffer, NULL);
  SwitchToFiber(pFiber);
  return 0;	
}	

After compiling and running our executable, we should see calc.exe pop up. Success!

Resources

MSDN: VirtualAlloc

MSDN: memcpy

MSDN: ConvertThreadToFiber

MSDN: CreateFiber

MSDN: SwitchToFiber

MSDN: Data Types

WikiBooks: Data Types