[RedDev Series #1] PE Injection Trick

GhouLSec
5 min readJan 12, 2020

Recently just found that process injection technique are quite widely used in malware (e.g. IcedID). However, there are a lot of process injection technique in the wild. Click here for more information.

In this post, I would like to demonstrate one of the process injection technique, PE injection with a simple PoC.

Here is the overall flow of my PoC.

  1. Spawn a new process that duplicate itself.
  2. Create a mutex to prevent the new child process from spawning itself again.
  3. VirtualAlloc to adjust the relocation table for the newly spawned process.
  4. Open process to create a handle form the spawned process
  5. VirtualAllocEx to allocate address to be written in spawned process address space.
  6. Writing payload to new process via write memory process.
  7. Create remote thread to write the payload into the newly spawned process and execute it by pointing it to the payload function address.

Descriptions

By uisng the Windows API, we can use CreateProcess() to a new process. To spawn a self identical process, use GetCommandLine() (It will be the full path of the file execution name,
e.g. C:\Users\user\Desktop\PoC.exe) as the second parameter in CreateProcess().

Create new self process

The newly spawned process will keep replicate itself as there is no proper control. Therefore, a mutex is needed to halt the self replication process. Shown as below:

Create new mutex to prevent unlimited spawning of self process

Next, to allocate the memory that need to be inject into new process, some PE header parsing is needed to get the image size of the current process image. IMAGE_OPTIONAL_HEADER.SizeOfImage is the size of the loaded executable/dll in virtual memory.

VirtualAlloc on self process

Create a handle for the spawned Process using OpenProcess(). Then, use VirtualAllocEx() to allocate the memory on the spawned process that will allocate for the payload.

Create handle for spawned process
VirtualAllocEx on spawned process

There is a problem arise here as when a new process starts, the base address of the module is unpredictable and different from each process.

In this case, there is a need to change the base address of all data described using full address pointer. For that, we are going to use the process relocation section.

Base Relocation

Base Relocation Table is a table of pointers to every absolute address used in the code. You may check here for more detailed explaination.

General steps for base relocation:
1. Get the base address of .reloc section.

2. Calculate the number of relocation descriptors.

3. Locate the address of data that need to be reallocate.
4. Replace it with new offset.

localImage is the during the runtime execution.

relocationTable->VirtualAddress = Virtual address of the .relocblock

relocationRVA[i].Offset = Offset of the descriptor items in the block

It will loop through the descriptor items in the .relocblock to rebase all the address at the last 12bit of descriptor as the it is the offset into the VirtualAddress of the containing relocation block.

Prove the value of relocationTable->VirtualAddress and relocationRVA[i].Offset in CFF Explorer

5. Move to next .reloc block.

6. Repeat (1–5). 👆

Writing Process and Payload Execution

After relocation finished, call WriteProcessMemory() to write the address of the new relocated based address into the spawned process and call CreateRemoteThread() to start the execution of the payload.

Write process memory:

CreateRemoteThread:

Here is the short Demo:

:D

This PoC really helps me to understand more about the PE structure and Process injection. It is very helpful when dealing with malware that using process injection technique.

Full code here.

Extra Notes:

One simple trick based on my experiment:

Always look for the “RWX” protection to find out the injected process in memory sections.

Injected code found :D

From VirtualAllocEx, we already able to identify the memory address that will used to allocate the injected code.

VirtualAllocEx shows the targeted memory address that will be used later

Mutant Created

From the main process, look for the Handles section to check for the created mutant. Since the mutant is already created in main process, the child identical process will not create it again.

Mutant/Mutex found ✌

PE header Structure:

PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)imageBase + dosHeader->e_lfanew);

The e_lfanew will skip to DOS Stub and points to the PE signature in the COFF (Common Object File Format) header. It will then points to the OptionalHeader to retrieve necessary PE information.

Source: StackOverFlow

References:

--

--